我的方案:我有一个异步tcp服务器接受连接,并在请求时使用此方法响应:
private void SendMessage(Client client, string message)
{
var buffer = Encoding.UTF8.GetBytes(message);
try
{
client.TCPClient.GetStream().Write(buffer, 0, buffer.Length);
}
catch (Exception ex) when (ex is InvalidOperationException || ex is System.IO.IOException)
{
RemoveClient(client);
Task exceptionHandler = Program.ExceptionHandler.Server(ex);
}
}
我有一个客户端应用程序,它使用此方法接收数据:
private string GetMessage()
{
StringBuilder returndata = new StringBuilder();
NetworkStream clientStream = this.tcpClient.GetStream();
var sr = new StreamReader(clientStream, Encoding.UTF8);
int value;
while (sr.Peek() >= 0 || clientStream.DataAvailable)
{
value = sr.Read();
returndata.Append((char)value);
}
return returndata.ToString();
}
大多数情况下,我发送使用JSON序列化的对象,它一直运行良好,直到现在。当我重新启动客户端时,它从服务器获取数据,但有时只有一部分到达,并且应用程序在JSON反序列化时因ArgumentException而崩溃。奇怪的是当它发生时(随机)sr.Peek()= -1但是clientStream.DataAvailable = true
另一个信息是,它总是在崩溃时读取消息是相同的。
任何人都可以帮助我什么可能导致有时我只得到一部分信息不是全部?
TCP API在两个方向上暴露双向字节流 - 而不是数据包API。您在一个套接字上写入流并在另一端读取它。但是,无法保证单个写入只会导致一个或多个读取。这是因为发送的字节可能会在多个IP数据包上分段,有些可能会延迟到达。
如果您想在应用程序层上使用数据包或消息,则需要引入自己的框架机制。
这样做的典型解决方案是:
您不能指望单次接收获取所有已发送的数据,您必须检查收到的字节数并检查它是否是完整的消息。