我有一个服务器,很大程度上是基于这tutorial.在我对其应用了额外的更改后,它工作正常.但现在我正试着给它加socket.io,它现在出现了一些问题.在测试我为socket.io添加的代码后,它似乎影响了使客户端代码(端点)调用服务器端代码(数据库查询、处理)的机制.当终端上出现端点呼叫的日志(log)时,呼叫到达服务器的客户端,但它似乎没有呼叫服务器端.

以下是套接字服务器的代码:

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的AN终结点时,我收到了这个错误,它是由调用服务器端代码的代码引发的:

"RPC错误:代码=不可用描述=连接错误:描述= "传输:拨号时出错:拨号tcp[::1]:50051:ConnectEx:no 由于目标计算机主动拒绝,因此可以建立连接 它.""

代码如下所示:

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))

要进行测试,您可以在其后面添加日志(log),并且不会打印该日志(log)消息.

你需要在不妨碍大猩猩的单独比赛中跑StartSocket()米.

附注:例如,这一行是log.Fatal(http.ListenAndServe(":8000", nil)).您的代码接受了一个错误.

Go相关问答推荐

Go PQ驱动程序无法使用默认架构进行查询

在不耗尽资源的情况下处理S3文件下载

mockgen不创建模拟

确定果朗CSV行中的字节数

如何根据地址和大小打印字符串

在golang二进制中嵌入SvelteKit

为什么我只收到部分错误而不是我启动的 goroutines 的所有错误?

linter 警告:返回值被忽略

替换字符串中的最后一个字符

没有任务角色的 AWS CDK ECS 任务定义

我在 go 中制作的递归函数有什么问题?

如何在 Docker 容器中使用私有存储库进行身份验证

为什么在单独的 go routine 中需要 wg.Wait() 和 close() ?

GqlGen - 在字段解析器中访问查询输入参数

在我的情况下,如何以正确的方式测试方法?

无法在 GORM 中排序

使用 delve 在容器中调试 Golang:container_linux.go:380:启动容器进程导致:exec:/dlv:stat /dlv:没有这样的文件或目录

从另一个没有重复的确定性 int

如何使用 context.WithCancel 启动和停止每个会话的心跳?

Gin中测试模式有什么用