You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义TCP连接创建Go RPC客户端调用卡住,用DialHTTP正常求排查

Go RPC客户端调用无限挂起问题解决

问题原因

你遇到的挂起问题核心是RPC协议不匹配:

  • rpc.NewClient基于纯TCP连接创建的客户端,默认使用Gob编码的原生RPC协议;
  • rpc.DialHTTP创建的客户端,使用的是HTTP封装的RPC协议。

你的服务端应该是采用HTTP模式启动的(比如通过rpc.HandleHTTP()配合http.ListenAndServe),所以纯TCP的Gob客户端无法和服务端完成通信,导致调用一直等待响应,最终无限挂起。

解决方案

方案1:调整服务端为纯TCP RPC模式

如果要继续使用自定义TCP连接创建客户端,需要将服务端改为纯TCP模式启动,示例代码:

package main

import (
    "log"
    "net"
    "net/rpc"
)

type UserRPC struct{}

func (u *UserRPC) AddUser(args interface{}, reply *interface{}) error {
    // 实现你的业务逻辑
    return nil
}

func main() {
    rpc.Register(new(UserRPC))
    listener, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatalf("listen failed: %v", err)
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Printf("accept failed: %v", err)
            continue
        }
        go rpc.ServeConn(conn)
    }
}

此时客户端用你原来的代码就能正常调用。

方案2:客户端手动适配HTTP RPC协议

如果服务端必须保持HTTP模式,又想自己创建TCP连接,需要手动向服务端发送HTTP RPC的请求头,示例代码:

taskGenConn, err := net.Dial("tcp", cfg.TaskGeneratorRPCUrl)
if err != nil {
    return err
}

// 发送HTTP POST请求头,符合Go RPC的HTTP协议规范
_, err = fmt.Fprintf(taskGenConn, "POST /_goRPC_ HTTP/1.0\r\nContent-Type: application/gob\r\n\r\n")
if err != nil {
    taskGenConn.Close()
    return err
}

avsTaskGeneratorClient := rpc.NewClient(taskGenConn)
err = avsTaskGeneratorClient.Call("UserRPC.AddUser", payload, &reply)
if err != nil {
    return err
}

内容的提问来源于stack exchange,提问作者Bhautik Chudasama

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 06:35:02