Go语言TCP JSON-RPC服务器错误捕获与客户端断开检测
问题解答
1. JSON-RPC服务器端捕获错误的方式
在Go的JSON-RPC框架中,错误捕获主要围绕两种场景处理:
业务逻辑错误捕获:在RPC方法内部直接处理业务异常,将需要传递给客户端的错误通过方法返回值返回(JSON-RPC会自动序列化该错误并传递给客户端),同时可在服务器端记录错误日志:
func (t *Arith) Add(args *Args, result *int) error { if args.A < 0 || args.B < 0 { err := fmt.Errorf("不允许传入负数:A=%d, B=%d", args.A, args.B) fmt.Println("服务器业务错误:", err) // 服务器端记录错误 return err } *result = args.A + args.B return nil }连接与协议级错误捕获:
jsonrpc.ServeConn会在连接关闭或发生底层协议错误时返回,可在goroutine中捕获其返回的错误,实现底层异常的监控:go func(conn net.Conn) { err := jsonrpc.ServeConn(conn) if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { fmt.Println("服务器连接错误:", err) } }(conn)
2. 检测客户端断开连接(无需心跳包)
Go的net.Conn没有内置断开回调机制,但可以利用jsonrpc.ServeConn的生命周期特性实现需求:jsonrpc.ServeConn会一直阻塞处理该连接上的RPC请求,直到客户端断开连接或发生错误时返回,只需在该函数返回后打印断开提示即可。
修改后的服务器代码如下:
package main import ( "fmt" "net" "net/rpc" "net/rpc/jsonrpc" "strings" ) type Arith int type Args struct { A, B int } func (t *Arith) Add(args *Args, result *int) error { *result = args.A + args.B return nil } func RunServer() { arith := new(Arith) rpc.Register(arith) listener, err := net.Listen("tcp", ":8080") if err != nil { fmt.Println("启动服务器失败:", err) return } defer listener.Close() for { conn, err := listener.Accept() if err != nil { fmt.Println("接受连接失败:", err) continue } // 启动goroutine处理连接,在ServeConn返回后打印断开信息 go func(c net.Conn) { // ServeConn阻塞直到连接关闭或出错 err := jsonrpc.ServeConn(c) // 过滤正常关闭的提示(可选) if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { fmt.Println("连接异常:", err) } fmt.Println("client disconnected!") c.Close() }(conn) } } func main() { RunServer() }
原理说明:
当客户端主动调用client.Close()断开连接,或因网络异常导致连接中断时,jsonrpc.ServeConn会退出阻塞并返回,后续的断开提示语句会自动执行。这种方式完全符合JSON-RPC框架的设计逻辑,不会像虚拟读取那样干扰协议解析流程。
内容的提问来源于stack exchange,提问作者qciccoretti
相关产品推荐
相关产品推荐

