大家遇到过TCP接收数据,字节切片过长丢失字符的问题吗?

DukeAnn · · 373 次点击 · 开始浏览    置顶
我的字节`len()`长度超出 14032 以后的就没用了,下面是代码 ```golang func (rc *rpcClient) Send(data map[string]interface{}) (string, error) { const long = 128 // 取出的字节切片 buf := make([]byte, long) //Buffer是一个实现了读写方法的可变大小的字节缓冲 resp := new(bytes.Buffer) //var resp string if rc.server.Ip == "" { fmt.Println("服务器连接参数错误") } // 建立连接 conn, err := net.DialTimeout("tcp", rc.server.Ip+":"+rc.server.Port, 1*time.Second) if err != nil { return resp.String(), errors.New("TCP 连接超时") } // 异常关闭连接 defer conn.Close() // 获取请求信息 byteData, err := json.Marshal(&data) // 发送请求 n, err := conn.Write(byteData) if err != nil { return resp.String(), errors.New("TCP 发送请求失败") } // 读取响应 n, err = conn.Read(buf) if err != nil { return resp.String(), errors.New("TCP 读取响应失败") } resp.Write(buf[0:n]) // 续读 for n == long { n, err = conn.Read(buf) resp.Write(buf[0:n]) } //fmt.Println("Reply from server ", rAddr.String(), resp) return resp.String(), nil } ``` 不清楚是什么限制了这个字节切片的长度,如果接收的信息不是很长就没有问题。 之前 `resp` 是个 `string` 类型每次从tcp读取完字节切片数据转成字符用`resp += string(buf[0:n])`拼接在后面直至读取完毕。`long`变量设置的是 10240,一直运转没有问题,直到有一个消息信息长度为25147的时候,就开始丢字符,只能接受14032个字符。然后将`long`改小,直到128才能完成接收所有字符串(150也行)。 然后我网上查高效的字节切片转字符串使用`bytes.Buffer` 类型,就把 resp 换成了`bytes.Buffer` 类型,然后相同的问题又出现了,只能读取 14032 长度的字节切片。 我有一个PHP版本的客户端读取超长字节没有问题,每次设置的是读取 10240 长度。可以排除服务端问题。 之前使用字符串拼接 `long = 128` 也可以全部接收完成 ## 问题 是golang 自身限制了字节切片长度吗? 为什么字符串拼接tcp响应的时候要把接受缓冲区设置的很小才能接受很长的字符串呢? 为什么时候用字节切片拼接统一转string的时候回出现字节切片不能接收全部字符串呢? 刚刚又调试了一下,发现了新问题就是 ```golang // 续读 for n == long { n, err = conn.Read(buf) resp.Write(buf[0:n]) } ``` 这部分代码的问题,因为有一次读取的时候 n<long 了程序认为是 TCP 接收完成了,其实还有数据,手动设置了接受次数就全部收到了。 为什么会出现TCP没有接收完成切片却没有读满呢?
第 1 条附言  · 
找到问题了,是判断TCP接收完成的代码有问题。改成如下判断就好了 ```golang // 读取响应 _, err = io.Copy(&resp, conn) if err != nil { return resp.String(), err } ```
373 次点击  
加入收藏 微博
9 回复  |  直到 2018-12-06 14:33:02
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传