在golang中使用net.TCPConn时,如何在不事先指定字节片长度的情况下进行读取?

在golang中使用net.TCPConn时,如何在不事先指定字节片长度的情况下进行读取?,tcp,go,Tcp,Go,我试图从与redis客户端(一个只运行redis cli的终端)的tcp连接读取一些消息。但是,net包的命令要求我输入一个切片作为参数。每当我给出一个没有长度的切片时,连接就会崩溃,go程序就会停止。我不确定我的字节消息需要多长。因此,除非我指定某个大得离谱的切片,否则这个连接将始终关闭,尽管这看起来很浪费。我在想,是否可以在不知道邮件长度的情况下保持连接?我很想为我的具体问题找到一个解决方案,但我觉得这个问题更一般。为什么我需要知道手边的长度?图书馆就不能给我一片正确大小的吗 或者人们建议什

我试图从与redis客户端(一个只运行redis cli的终端)的tcp连接读取一些消息。但是,net包的命令要求我输入一个切片作为参数。每当我给出一个没有长度的切片时,连接就会崩溃,go程序就会停止。我不确定我的字节消息需要多长。因此,除非我指定某个大得离谱的切片,否则这个连接将始终关闭,尽管这看起来很浪费。我在想,是否可以在不知道邮件长度的情况下保持连接?我很想为我的具体问题找到一个解决方案,但我觉得这个问题更一般。为什么我需要知道手边的长度?图书馆就不能给我一片正确大小的吗


或者人们建议什么其他解决方案?

不知道消息大小正是您必须指定读取大小的原因(这适用于任何网络库,而不仅仅是Go)。TCP是一种流协议。就TCP协议而言,消息将一直持续到连接关闭

如果你知道你要一直读到EOF,使用

调用
Read
并不能保证得到您所期望的一切。它可能会返回更少,也可能返回更多,这取决于您收到的数据量。执行IO的库通常通过“缓冲区”进行读写;您将拥有您的“读取缓冲区”,这是一个预先分配的字节片(通常高达32k),每次您想要从网络读取时,您都会重复使用该片。这就是IO函数返回字节数的原因,这样您就知道上次操作填充了多少缓冲区。如果缓冲区已满,或者您仍需要更多数据,您只需再次调用
Read

有点晚,但

  • 其中一个问题是如何确定消息大小。JimB给出的答案是TCP是一种流协议,因此没有真正的终端
  • 我相信这个答案是错误的。TCP将比特流分成连续的数据包。每个数据包都有一个IP报头和一个TCP报头,请参阅和。每个数据包的IP报头包含该数据包长度的字段。您需要做一些数学运算来减去TCP报头长度,以获得实际的数据长度。 此外,可以在TCP标头中指定消息的最大长度
  • 因此,您可以为读取操作提供足够长度的缓冲区。但是,您必须首先读取数据包头信息。如果最大消息大小超过您愿意接受的长度,您可能不应该接受TCP连接
  • 通常,发送方将使用fin数据包(请参阅)而不是EOF字符终止连接
  • 读取操作中的EOF很可能表示包未在分配的时间内完全传输

  • 你能发布错误消息吗?是的,错误是
    EOF
    ,然后是
    exit status 1
    。我不介意反手切球,但事先切球只能在全场防守时使用,或者偶尔在转场时使用。哦,谢谢!我只是不明白,为什么有人不读到消息的结尾?在消息结束之前,EOF是否相同?为什么这个细节不是从程序员那里隐藏/抽象出来的?为什么在任何网络库中都会出现这种情况?EOF不是消息的结尾,而是连接正在关闭。TCP不仅仅用于发送单个数据块,它还是一个可以用来发送和接收消息的流。网络连接甚至不知道“消息”是什么,这取决于应用程序如何确定数据的帧。@Pinocchio,这就是为什么经常使用来实现应用程序级协议,这些协议使用基于流的协议,如TCP。