duanlu6268 2014-09-10 13:04
浏览 36
已采纳

Golang:TCP客户端/服务器数据定界符

Not sure how to formulate the question and if it really relates only to go language, but what i am trying to do is to have a tcp server and client that will exchange data in between, basically the client will stream big amounts of data into smaller chunks to the server, the server will wait to read every chunk of data and then reply with a status code which will be read by the client and based on that it will do other work.

I use the function below as a test to read the data from client and server (please note, i am aware that is not perfect, but it's just testing) :

func createBufferFromConn(conn net.Conn) *bytes.Buffer {
    buffer := &bytes.Buffer{}
    doBreak := false
    for {
        incoming := make([]byte, BUFFER_SIZE)

        conn.SetReadDeadline(time.Now().Add(time.Second * 2))
        bytesRead, err := conn.Read(incoming)
        conn.SetReadDeadline(time.Time{})

        if err != nil {
            if err == io.EOF {
                fmt.Println(err)
            } else if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
                fmt.Println(err)
            }
            doBreak = true
        }

        if doBreak == false && bytesRead == 0 {
            continue
        }

        if bytesRead > 0 {
            buffer.Write(incoming[:bytesRead])
            if bytes.HasSuffix(buffer.Bytes(), []byte("|")) {
                bb := bytes.Trim(buffer.Bytes(), "|")
                buffer.Reset()
                buffer.Write(bb)
                doBreak = true
            }
        }

        if doBreak {
            break
        }
    }
    return buffer
}

Now in my case if i connect via telnet(the go code also includes a client() to connect to the server()) and i type something like test 12345| fair enough everything works just fine and the buffer contains all the bytes written from telnet(except the pipe which is removed by the Trim() call).

If i remove the if bytes.HasSuffix(buffer.Bytes(), []byte("|")) { block from the code then i will get a timeout after 2 seconds, again, as expected because no data is received in that amount of time and the server closes the connection, and if i don't set a read deadline from the connection, it will wait forever to read data and will never know when to stop.

I guess my question is, if i send multiple chunks of data, do i have to specify a delimiter of my own so that i know when to stop reading from the connection and avoid waiting forever or waiting for the server to timeout the connection ?

  • 写回答

1条回答 默认 最新

  • dongshang1979 2014-09-10 13:09
    关注

    I guess my question is, if i send multiple chunks of data, do i have to specify a delimiter of my own so that i know when to stop reading from the connection and avoid waiting forever or waiting for the server to timeout the connection

    Yes. TCP is a stream protocol, and there's no way to determine where messages within the protocol start and stop without framing them in some way.

    A more common framing method used is to send a size prefix, so that the receiver knows how much to read without having to buffer the results and scan for a delimiter. This can be as simple as message_length:data.... (see also netstring, and type-length-value encoding).

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100