如何在TCP客户端中读取未知数据长度

时间:2014-09-07 17:13:52

标签: c# tcp bytearray tcpclient

我是C#的新相对论。在我的TCP客户端中有以下功能,它将数据发送到服务器并返回响应:

private static TcpClient tcpint = new TcpClient(); //Already initiated and set up
private static NetworkStream stm;                  //Already initiated and set up

private static String send(String data)
{
    //Send data to the server
    ASCIIEncoding asen = new ASCIIEncoding();
    byte[] ba = asen.GetBytes(data);
    stm.Write(ba, 0, ba.Length);

    //Read data from the server
    byte[] bb = new byte[100];
    int k = stm.Read(bb, 0, 100);

    //Construct the response from byte array to string
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < k; i++)
    {
        sb.Append(bb[i].ToString());
    }

    //Return server response
    return sb.ToString();
}

正如你在这里看到的,当我从服务器读取响应时,我将其读入一个长度为100字节的fix byte []数组。

byte[] bb = new byte[100];
int k = stm.Read(bb, 0, 100);

如果来自服务器的响应超过100个字节,我该怎么办?如何在不知道服务器的最大数据长度是什么的情况下读取数据?

4 个答案:

答案 0 :(得分:1)

通常,在没有某些特定内在大小的情况下,tcp协议会明确发送它们发送的对象的长度。一种可能的说明方法:

size_t data_len = strlen(some_data_blob);
char lenstr[32];
sprintf(lenstr, "%zd\n", data_len);
send(socket, lenstr, strlen(lenstr));
send(socket, some_data_blob, data_len);

然后当接收者读取长度字符串时,它确切知道应该遵循的数据量(良好的编程习惯是信任但是验证 - 如果有更多或者更少的数据真的被发送 - 比如一个'邪恶的演员' - 你需要准备好处理它。)

答案 1 :(得分:1)

不是关于C#而是关于编写TCP应用程序的一般答案:

TCP是基于蒸汽的协议。它不保持消息边界。因此,使用TCP的应用程序应该注意选择正确的服务器和客户端之间的数据交换方法。如果在一个连接上发送和接收多条消息,它就变得更加重要。

一种广泛使用的方法是在数据消息前加上长度字节。

例如:

[2 byte -length field][Actual Data]

此类数据的接收者(无论是服务器还是客户端都需要解码长度字段,等待直到收到这么多字节的事件或者在超时时发出警报并放弃。

可以使用的另一个协议是让应用程序维护消息边界。

例: `[MSG开始] [实际数据] [MSG结束]

接收方必须解析开始字节和结束字节(由应用程序协议预定义)的数据,并将其间的任何内容视为感兴趣的数据。

答案 2 :(得分:0)

你好,我用一个清单解决了它,我不知道完整包装的大小,但我可以阅读它的部分

List<byte> bigbuffer = new List<byte>();

byte[] tempbuffer = new byte[254]; 
//can be in another size like 1024 etc.. 
//depend of the data as you sending from de client
//i recommend small size for the correct read of the package

NetworkStream stream = client.GetStream();

while (stream.Read(tempbuffer, 0, tempbuffer.Length) > 0) {

    bigbuffer.AddRange(tempbuffer);
} 

// now you can convert to a native byte array
byte[] completedbuffer = new byte[bigbuffer.Count];

bigbuffer.CopyTo(completedbuffer);

//Do something with the data
string decodedmsg = Encoding.ASCII.GetString(completedbuffer);

我这样做的图像和看起来很好,我知道如果porpouse被读取一个未知大小的完整来源你不知道数据的大小

答案 3 :(得分:0)

我正在四处寻找答案,并注意到Available属性已添加到TcpClient。它返回可读取的字节数。

我假设它是在大多数答复之后添加的,所以我想与其他可能会遇到此问题的人分享。

https://docs.microsoft.com/en-us/dotnet/api/system.net.sockets.tcpclient.available?view=netframework-4.8