我有一个很大程度上基于本教程的服务器。在我对其应用了额外的更改后,它工作得很好。但现在我尝试向其中添加 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///api/proto/out"
"github.com///cmd/server/handlers"
"github.com///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///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 error: code = unavailable desc = connection error: desc =
"transport: error while dialing: dial tcp [::1]:50051: connectex: no
connection could be made because the target machine actively refused
it.""
代码如下:
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))
为了测试,您可以在其后面添加日志,并且该日志消息将不会打印。
您需要在单独的非阻塞 goroutine 中运行 StartSocket()
。
附注例如,该行是 log.Fatal(http.ListenAndServe(":8000", nil))
。您的代码吞下了一个错误。
以上就是启动套接字服务器会干扰 gRPC/http 客户端服务器通信 Golang的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756