如何获取带有消息结尾字符的 TCP 消息中的所有数据?
How to get all data in a TCP message with an end of message character?
我有一个 TCP 客户端/服务器应用程序,它在本地机器上运行良好。然而,当我在另一台机器上使用客户端时,只传递了小消息(最多 20-30 字节)。如果锁定,客户端需要读取更大数据的那一刻。我认为问题在于客户端没有接收到一个 tcp 数据包中发送的所有数据。所以换句话说,我只调用了一次 tcpClient.Client.Receive(tcpBuffer) 并假设 tcpBuffer 拥有它在本地机器上所做的所有数据。现在服务器发送的消息都以消息中唯一的字节 (0xFD) 终止。我不知道该如何处理。所以一个问题是,NetworkStream.DataAvailable 提供的数据是在客户端还是在服务器上提供的?我是否必须继续阅读和循环直到获得 0xFD 值?如何才能有效地做到这一点?
所以基本上我想用以下内容替换 tcpClient.Client.Receive(tcpBuffer):
private static byte[] GetTcpResponse()
{
int arrayLength = tcpClient.Client.Receive(tcpBuffer);
if (tcpBuffer[arrayLength - 1] == 0xFD)
{
return tcpBuffer;
}
else
{
//this is where I am hung up
}
}
所以我挂的地方从上面可以看出。我只是再做一次接收吗?如果还没有数据怎么办?
谢谢,汤姆
TCP 是一种基于流的 协议,它是而非一种基于数据报的 协议。您不应该依赖于接收到的具有给定大小的数据报或您的数据位于任何给定的数据报边界上;您也不应期望所有数据都在一个数据报(或任何给定数量的数据报)上接收。所以当你说:
Do I have to keep reading and looping until I get the 0xFD value?
是的,这就是重点; 但 添加合理的超时和适当的异常检查,这样您的应用程序就不会挂起,以防连接失败并且您永远无法获得该终止值。
你的代码可能是这样的(除了超时、错误检查等);我还没有测试过,但它应该可以帮助您理解:
private static byte[] GetTcpResponse()
{
var data = new List<byte>();
var buffer = new byte[512]; //size can be different, just an example
var terminatorReceived = false;
while(!terminatorReceived)
{
var bytesReceived = tcpClient.Client.Receive(buffer);
if(bytesReceived > 0)
{
data.AddRange(buffer.Take(bytesReceived));
terminatorReceived = data.Contains(0xFD);
}
}
return data.ToArray();
}
我有一个 TCP 客户端/服务器应用程序,它在本地机器上运行良好。然而,当我在另一台机器上使用客户端时,只传递了小消息(最多 20-30 字节)。如果锁定,客户端需要读取更大数据的那一刻。我认为问题在于客户端没有接收到一个 tcp 数据包中发送的所有数据。所以换句话说,我只调用了一次 tcpClient.Client.Receive(tcpBuffer) 并假设 tcpBuffer 拥有它在本地机器上所做的所有数据。现在服务器发送的消息都以消息中唯一的字节 (0xFD) 终止。我不知道该如何处理。所以一个问题是,NetworkStream.DataAvailable 提供的数据是在客户端还是在服务器上提供的?我是否必须继续阅读和循环直到获得 0xFD 值?如何才能有效地做到这一点? 所以基本上我想用以下内容替换 tcpClient.Client.Receive(tcpBuffer):
private static byte[] GetTcpResponse()
{
int arrayLength = tcpClient.Client.Receive(tcpBuffer);
if (tcpBuffer[arrayLength - 1] == 0xFD)
{
return tcpBuffer;
}
else
{
//this is where I am hung up
}
}
所以我挂的地方从上面可以看出。我只是再做一次接收吗?如果还没有数据怎么办? 谢谢,汤姆
TCP 是一种基于流的 协议,它是而非一种基于数据报的 协议。您不应该依赖于接收到的具有给定大小的数据报或您的数据位于任何给定的数据报边界上;您也不应期望所有数据都在一个数据报(或任何给定数量的数据报)上接收。所以当你说:
Do I have to keep reading and looping until I get the 0xFD value?
是的,这就是重点; 但 添加合理的超时和适当的异常检查,这样您的应用程序就不会挂起,以防连接失败并且您永远无法获得该终止值。
你的代码可能是这样的(除了超时、错误检查等);我还没有测试过,但它应该可以帮助您理解:
private static byte[] GetTcpResponse()
{
var data = new List<byte>();
var buffer = new byte[512]; //size can be different, just an example
var terminatorReceived = false;
while(!terminatorReceived)
{
var bytesReceived = tcpClient.Client.Receive(buffer);
if(bytesReceived > 0)
{
data.AddRange(buffer.Take(bytesReceived));
terminatorReceived = data.Contains(0xFD);
}
}
return data.ToArray();
}