启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang

2024-04-19

我有一个很大程度上基于此的服务器tutorial https://www.golinuxcloud.com/go-grpc-crud-api-postgresql-db/。在我对其应用了额外的更改后,它工作得很好。但现在我想添加socket.io对此,它现在遇到了一些问题。测试代码后socket.io我添加的,它似乎影响了客户端代码(端点)调用服务器端代码(数据库查询、处理)的机制。当端点调用的日志出现在终端上时,调用到达服务器的客户端,但它似乎并未调用服务器端。

这是套接字服务器的代码:

package helpers

import (
    "fmt"
    "net/http"

    socketio "github.com/googollee/go-socket.io"
    "github.com/googollee/go-socket.io/engineio"
    "github.com/googollee/go-socket.io/engineio/transport"
    "github.com/googollee/go-socket.io/engineio/transport/polling"
    "github.com/googollee/go-socket.io/engineio/transport/websocket"
)

var allowOriginFunc = func(r *http.Request) bool {
    return true
}

func StartSocket() {
    server := socketio.NewServer(&engineio.Options{
        Transports: []transport.Transport{
            &polling.Transport{
                CheckOrigin: allowOriginFunc,
            },
            &websocket.Transport{
                CheckOrigin: allowOriginFunc,
            },
        },
    })

    server.OnConnect("/", func(s socketio.Conn) error {
        s.SetContext("")
        fmt.Println("connected:", s.ID())
        return nil
    })

    server.OnEvent("/", "notice", func(s socketio.Conn, msg string) {
        fmt.Println("notice:", msg)
        s.Emit("reply", "have "+msg)
    })

    server.OnError("/", func(s socketio.Conn, e error) {
        fmt.Println("socket error:", e)
    })

    server.OnDisconnect("/", func(s socketio.Conn, reason string) {
        fmt.Println("closed", reason)
    })

    go server.Serve()
    defer server.Close()

    http.Handle("/socket.io/", server)
    http.Handle("/", http.FileServer(http.Dir("./asset")))

    fmt.Println("Socket server serving at localhost:8000...")
    fmt.Print(http.ListenAndServe(":8000", nil))
}

// main.go 服务器端

package main

import (
    "flag"
    "fmt"
    "log"
    "net"

    pb "github.com/<me>/<project_name>/api/proto/out"
    "github.com/<me>/<project_name>/cmd/server/handlers"
    "github.com/<me>/<project_name>/cmd/server/helpers"

    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

func init() {
    helpers.DatabaseConnection()
}

var (
    tls      = flag.Bool("tls", true, "Connection uses TLS if true, else plain TCP")
    certFile = flag.String("cert_file", "", "The TLS cert file")
    keyFile  = flag.String("key_file", "", "The TLS key file")
    port     = flag.Int("port", 50051, "The server port")
)

func main() {
    flag.Parse()

    // helpers.StartSocket()

    lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", *port))
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }

    var opts []grpc.ServerOption
    if *tls {
        if *certFile == "" {
            *certFile = "service.pem"
        }

        if *keyFile == "" {
            *keyFile = "service.key"
        }

        creds, err := credentials.NewServerTLSFromFile(*certFile, *keyFile)

        if err != nil {
            log.Fatalf("Failed to generate credentials: %v", err)
        }

        opts = []grpc.ServerOption{grpc.Creds(creds)}
    }

    mServ := grpc.NewServer(opts...)

    fmt.Println("gRPC server running ...")

    pb.RegisterSomethingServiceServer(mServ, &handlers.SomethingServer{})

    log.Printf("Server listening at %v", lis.Addr())
    
    if err := mServ.Serve(lis); err != nil {
        log.Fatalf("failed to serve : %v", err)
    }
}

// main.go 客户端

package main

import (
    "bytes"
    "encoding/json"
    "flag"
    "fmt"
    "log"
    "sort"
    "strings"

    "github.com/<me>/<project_name>/cmd/client/handlers"

    "github.com/gin-gonic/gin"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials"
)

var (
    addr = flag.String("addr", "localhost:50051", "the address to connect to")
)

func main() {
    flag.Parse()

    creds, err := credentials.NewClientTLSFromFile("service.pem", "")

    if err != nil {
        log.Fatalf("could not process the credentials: %v", err)
    }

    conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(creds))

    if err != nil {
        log.Fatalf("did not connect: %v", err)
    }

    defer conn.Close()

    var ginGine = gin.Default()
    StartClient(conn, ginGine)
}

func StartClient(conn *grpc.ClientConn, ginGine *gin.Engine) {

    handlers.SomethingApiHandler(conn, ginGine)

    ginGine.Run(":5000")
}

对于完整的客户端和服务器代码,您可以查看我上面链接的教程。如果我不打电话StartSocket(),一切正常。

当调用 API 的端点时,我收到此错误,该错误是由调用服务器端代码的代码引发的:

“rpc 错误:代码 = 不可用 desc = 连接错误:desc = “传输:拨号时出错:拨打 tcp [::1]:50051: connectex: 否 由于目标机器主动拒绝而无法建立连接 它。””

代码如下所示:

ginGine.POST("/account/login", func(ctx *gin.Context) {
    var account models.Account

    err := ctx.ShouldBind(&account)
    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error1": err.Error(),
        })
        return
    }

    res, err := srvClient.service.ValidateAccount(ctx, &pb.ValidateAccountRequest{
        Account: &pb.Account{
            Id:        account.ID,
            FirstName: account.FirstName,
            LastName:  account.LastName,
            UserName:  account.UserName,
            Password: account.Password,
        },
    })

    if err != nil {
        ctx.JSON(http.StatusBadRequest, gin.H{
            "error2": err.Error(),
        })
        return
    }

    ctx.JSON(http.StatusOK, gin.H{
        "status":       res.Status,
        "access_token": res.AccessToken,
    })
})

error2 是 API 调用返回的内容


这行代码是阻塞且函数StartSocket()永不返回:

fmt.Print(http.ListenAndServe(":8000", nil))

为了测试,您可以在其后面添加日志,并且该日志消息将不会打印。

你需要跑StartSocket()在一个单独的非阻塞 goroutine 中。

附:例如,该行是log.Fatal(http.ListenAndServe(":8000", nil))。你的代码吞掉了一个错误。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang 的相关文章

  • 如何使用 go 1.5+ 创建静态链接的 golang 可执行文件

    golang 版本 1 5 怎么样 谷歌搜索没有为我的搜索词返回任何有用的结果 有人对如何生成可以在基本 rkt 来自 CoreOS 容器内执行的静态链接二进制文件有任何建议吗 my go go version go version go1
  • 指定共享对象(共享库)的名称

    Go 编译器为共享对象生成的名称是错误的 例子 go install buildmode shared linkshared github com apache thrift lib go thrift code google com p
  • Golang:我可以投射到 chan 接口吗{}

    我正在尝试为订阅编写一个通用包装器 例如 type Subscriber interface Subscribe addr string chan interface 假设有一个我想使用的库 其中有一个 subscribe 方法 但它使用c
  • golang - 省略 json 属性进行序列化的优雅方法

    我有一个用户结构 其中包含密码等敏感字段 type User struct UID string json uid binding required Password string json password binding require
  • 如何列出已安装的 go 软件包

    据我所知go distribution带有某种package manager After go 1 4 1我已经运行的安装go help为了找到任何能够列出本地安装的子命令go packages 但不幸的是没有 那么该怎么做呢 goinst
  • 为什么我无法导入“内置”pkg?

    cat test go package main import builtin func main return go run test go can t find import builtin 我只是好奇 因为该文件存在并且已正确打包 但
  • 使用 Go 解组嵌套 xml

    我有以下代码片段 我一直在努力让它工作 我到处寻找解决方案 但我找到的解决方案似乎都不起作用 我的映射似乎有问题xml Unmarshal命令 因为它涉及嵌套字段 下面的代码用于检索第一个被称为的值unit 并且位于 xml 代码的顶层 另
  • Golang xml.Unmarshal 接口类型

    使用xml我在解组非同质类型列表时遇到问题 考虑以下 XML 文档 其嵌套元素是非同质类型的列表
  • 为什么 Go 中无法将 [Size]byte 转换为字符串?

    我有一个大小字节数组 是我做完之后得到的md5 Sum data byte testing var pass string var b 16 byte b md5 Sum data pass string b 错误 cannot conve
  • 如何获取变量的内存大小?

    有谁知道如何获取变量的内存大小 int string struct等 并打印它 是否可以 var i int 1 I want to get something like this fmt Println Size of i is i Al
  • golang 范围内的指针不起作用

    为什么结果是A 1 A 2 A 2 not A 1 A 2 A 3 我们不能在范围内使用指针吗 这是代码 我设置了一个指针 指向范围循环 但它失败了 package main import fmt type A struct Barry B
  • 处理变量的范围:内部循环

    作为一名直接进入 Go 的 JS 开发者 如果长度超过commits不止一个 我没有太多时间来完成这件事 而且我搜索的时间比我希望的要长 关于如何重组它或让它发挥作用有什么想法吗 case github PushPayload push p
  • 重写 ResponseWriter 接口以捕获 HTTP 错误

    我正在用 Go 编写一个 Web 应用程序 虽然各种 mux 库提供了一种设置自定义 404 错误处理程序的方法 但没有任何其他 4xx 和 5xx 错误代码 一个建议是重写 ResponseWriter 接口中的 WriteHeader
  • 从 C 调用带有字符串参数的 Go 函数?

    我可以从 C 调用一个没有参数的 Go 函数 按照下面的 https github com joeprivacy crefgo hello world 这通过编译go build和打印 Hello from Golang main func
  • 识别推文消息中正确的主题标签索引

    我需要识别 Twitter 消息 各种语言 表情符号等 中的正确索引 我找不到返回这些位置的解决方案 如下例所示 import regexp testing github com stretchr testify require func
  • ConstantTimeByteEq 如何工作?

    在大神的密码库里 找到了这个函数ConstantTimeByteEq http golang org src pkg crypto subtle constant time go s 897 936 L17 它有什么作用 如何工作 Cons
  • 如何更新任意go结构的所有字符串字段?

    我尝试编写一个函数来更新所有字符串字段随意的结构体 像这样 type Student struct Name string Age int func SetStringField obj interface reflect ValueOf
  • 如何分发仅二进制的 go 包

    我想以二进制形式分发包而不包含源代码 我的演示项目目录结构是这样的 demo greet greet go hi hi go hello hello go main go main go package main import fmt de
  • Python 中的 Socket.IO 客户端库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 谁能推荐一个 Python 的 Socket IO 客户端库 我环顾四周 但我能找到的唯一的要么是服务
  • 读取一个文本文件,替换其中的单词,输出到另一个文本文件

    所以我试图在 GO 中编写一个程序来获取一个充满代码的文本文件并将其转换为 GO 代码 然后将该文件保存到 GO 文件或文本文件中 我一直在试图弄清楚如何保存对文本文件所做的更改 但我可以看到更改的唯一方法是通过 println 语句 因为

随机推荐

  • Flash AS3 - 将多个对象拖放到一个目标?

    标题或多或少是不言自明的 我一直在学习许多不同的教程 而且说实话 我对 AS3 不太擅长 上图显示了我的目标 无论如何 我在我看到的大多数在线教程中注意到 拖放教程要么基于一个对象到一个目标 要么基于多个对象到多个目标 所以我想知道是否有人
  • 如何让php函数每5秒循环一次

    我正在尝试创建一个每秒更新一次的 php 函数 使用 php 本身 没有其他语言 只是纯 PHP 代码 function exp do something 我希望它每秒返回一个值 就像每秒更新一样 对于应用程序服务器 不是 Web 服务器
  • 让 WordPress 使用页面而不是类别

    我做了大量的研究并发现了一些像这样的解决方案 https wordpress stackexchange com questions 106042 force wordpress to show pages instead of categ
  • VS 2008 Addon 暂时禁用/删除所有 catch 块

    是否有任何插件可以暂时禁用所有 catch 块 我正在维护一个应用程序 我需要找出它到底在哪里抛出异常 有人已经完成了错误处理 所有层都完成了 这使我的工作变得艰难 我不知道如何禁用 catch 块 但您想要实现的目标可以通过异常对话框中的
  • 如何设置微调器下拉列表的最大长度?

    我有一个微调器 当前打开时会遮挡微调器下方的一些文本 我需要通过 java 代码或 XML 来限制微调器的最大下拉长度 这样它就不会模糊此文本 The current design is the left example while the
  • 获取错误消息

    我们使用以下代码在验证文档时添加新的错误消息 function addFacesMessage message component try if typeof component string component getComponent
  • Firebase Push() 与 Angularfire $save()

    angularfire save 与 firebase push 相比如何 我知道 Push 在存储数据时会生成一个唯一的密钥 但我无法使用 AngularFire 重新创建该行为 有没有办法或者我应该使用 push 如果是这样 在什么情况
  • 消除在 Swift 中连续绘制 UIBezierPath 期间的滞后延迟

    下面的代码通过覆盖触摸来绘制线条 但是在连续不间断绘制的一段时间内开始出现滞后 手指在屏幕上移动的时间越长 这种滞后就会累积并变得更严重 结果是实际设备上的 CPU 几乎达到极限 CPU 98 并且绘图持续时间越长 生成的图像看起来就越不稳
  • 获取 Disqus html 代码以显示在源代码中以实现 SEO 目的

    最近开始在网站上使用 Disqus 想知道是否有任何方法可以让实际的 html 代码显示在源页面中 我注意到这个网站正在这样做 http adamkaras com blog 2009 06 24 disqus custom css sty
  • 鼠标悬停 div 时弹出消息

    尝试让一个简单的弹出窗口出现mouseover a div我按照答案使用 onmouseover 的描述框 https stackoverflow com questions 3559467 description box on mouse
  • 如何从 java.util.Map 转换为 Scala Map

    Java API 返回一个java util Map
  • 在 Fantasy Football 阵容优化器中添加 Flex 位置

    我编写了一些 R 代码来生成最佳的幻想足球阵容 最大化预计得分 该阵容受到用户输入的名单大小和选秀预算的约束 该数据框基于称为 球员 的数据框 该数据框由球员 位置 幻想点和选秀组成价值 我们的想法是在选秀之前使用这个工具 记住理想的阵容
  • 如何使用线性索引在多维数组中设置值

    使用线性索引在 C 多维数组中设置值的最有效方法是什么 例如给定一个数组 int arr2 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 如何使
  • 用于图像中文本检测的霍夫变换算法[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 霍夫变换算法是用于文本行检测和边缘检测的算法之一 霍夫变换算法可以用于检测图像中的文本吗 这道题在java中的流程或者实现应该是怎样的
  • 在 JavaScript 中将浮点数转换为整数的最佳方法是什么?

    在 JavaScript 中 有多种不同的方法可以将浮点数转换为整数 我的问题是哪种方法可以提供最佳性能 最兼容或被认为是最佳实践 以下是我所知道的几种方法 var a 2 5 window parseInt a 2 Math floor
  • 如何在 Android 中强制蓝牙 LE“正常工作”配对

    我有一个运行 GATT 服务器的嵌入式系统 我尝试通过 Android 连接该服务器 任务很简单 连接到 GATT 服务器 导航特征并验证读 写功能 问题是当我尝试连接 Android 应用程序时 它尝试与 Passkey 而不是 Just
  • Node.js 中硬编码的 mysql 用户和密码

    我将 mysql 与 node js 一起使用 像这样的东西 var mysql require mysql var connection mysql createConnection host localhost user me pass
  • Python 3 中的 FastCGI WSGI 库?

    对于 Python 3 是否存在可以将 WSGI 应用程序用作 FastCGI 服务器的库 这样 nginx 就可以将请求代理给它了 Python 3 文档 https docs python org 3 howto webservers
  • 重定向子进程标准输出

    我已经使用 test py 中的 Redir 类设置了标准输出重定向 如下 输出应在文本框中显示两个打印语句 但目前只有 Output1 被发送到文本框 Output2 在后面的控制台中打印 我想知道是否有办法重定向子进程的标准输出 我尝试
  • 启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang

    我有一个很大程度上基于此的服务器tutorial https www golinuxcloud com go grpc crud api postgresql db 在我对其应用了额外的更改后 它工作得很好 但现在我想添加socket io