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

问题描述 投票:0回答:4

我是 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 字节的固定 byte[] 数组中。

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

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

c# tcp arrays tcpclient
4个回答
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
投票

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

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);

我用图像做这个,看起来不错,我认为如果海豚读取了未知大小的完整源,你不知道数据的大小


1
投票

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

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

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

例如:

[2 byte -length field][Actual Data]
.

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

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

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

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


0
投票

我四处寻找这个问题的答案,并注意到可用属性已添加到 TcpClient。它返回可供读取的字节数。

我假设它是在大多数回复之后添加的,所以我想与可能偶然发现这个问题的其他人分享。

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

© www.soinside.com 2019 - 2024. All rights reserved.