动态输入数据时 TCP 服务器无法正确接收
TCP Server not receiving properly when data is dynamicaly typed
我正在开发一个简单的 TCP 服务器应用程序,它从流中接收数据并将其存储在列表中。
当每个连接在一条消息中发送数据时,我已成功获取数据。我的问题似乎是在从命令行使用 telnet 对其进行测试时。我将开始打字,程序将根据我的打字速度抓取一两个字符,然后不再从该流中接收任何内容。我真的不知道为什么。如果我在 stream.DataAvailable 循环中放置一个 thread.sleep,那么它会得到更多的字符,但会再次停止。任何帮助表示赞赏。我的class如下:
public class TCPServer
{
private TcpListener listener;
public List<string> messages;
public TCPServer(IPAddress ip, int port)
{
try
{
messages = new List<string>();
listener = new TcpListener(ip, port);
listener.Start();
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ClientConnected(IAsyncResult ar)
{
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
string message = "";
while (!stream.DataAvailable)
{
}
while (stream.DataAvailable)
{
byte[] readBytes = new byte[65536];
stream.Read(readBytes, 0, readBytes.Length);
message += Encoding.ASCII.GetString(readBytes).TrimEnd('[=10=]');
}
if (message != null)
{
messages.Add(message);
message = "";
}
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
public void Stop()
{
listener.Stop();
}
}
阅读循环非常不正确。
您误解了 DataAvailable
没有告诉您将到达多少字节。它给你一个下限,可能随时说 0。循环将提前中止。使用 DataAvailable
几乎总是不正确的。
这无济于事,是一个忙碌的等待,应该向您发出警告信号:
while (!stream.DataAvailable)
{
}
正确的阅读方式是直接调用Read
。您需要使用 Read
中的 return 值来查看已到达的字节数。修剪零是不正确的(你不能那样接收零)和一个 hack,再次,应该在精神上发出危险信号!这不是正确的做法。
套接字很难正确。不要进行可疑的黑客攻击,这只会增加不确定性故障的可能性。
所以我通过深入研究 NetworkStream class 设法解决了这个问题。在 BeginReceiveTcpClient 的回调中,我从 tcpclient 中提取了网络流,因此我可以访问 BeginReceive 异步方法。相关代码如下:
private void ClientConnected(IAsyncResult ar)
{
byte[] readBytes = new byte[65536];
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ReadStream(IAsyncResult ar)
{
try
{
NetworkStream stream = (NetworkStream)ar.AsyncState;
int bytesRead = stream.EndRead(ar);
content += Encoding.ASCII.GetString(buffer, 0, bytesRead);
dataProcessor.ProcessData(messages);
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
我正在开发一个简单的 TCP 服务器应用程序,它从流中接收数据并将其存储在列表中。
当每个连接在一条消息中发送数据时,我已成功获取数据。我的问题似乎是在从命令行使用 telnet 对其进行测试时。我将开始打字,程序将根据我的打字速度抓取一两个字符,然后不再从该流中接收任何内容。我真的不知道为什么。如果我在 stream.DataAvailable 循环中放置一个 thread.sleep,那么它会得到更多的字符,但会再次停止。任何帮助表示赞赏。我的class如下:
public class TCPServer
{
private TcpListener listener;
public List<string> messages;
public TCPServer(IPAddress ip, int port)
{
try
{
messages = new List<string>();
listener = new TcpListener(ip, port);
listener.Start();
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ClientConnected(IAsyncResult ar)
{
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
string message = "";
while (!stream.DataAvailable)
{
}
while (stream.DataAvailable)
{
byte[] readBytes = new byte[65536];
stream.Read(readBytes, 0, readBytes.Length);
message += Encoding.ASCII.GetString(readBytes).TrimEnd('[=10=]');
}
if (message != null)
{
messages.Add(message);
message = "";
}
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
public void Stop()
{
listener.Stop();
}
}
阅读循环非常不正确。
您误解了 DataAvailable
没有告诉您将到达多少字节。它给你一个下限,可能随时说 0。循环将提前中止。使用 DataAvailable
几乎总是不正确的。
这无济于事,是一个忙碌的等待,应该向您发出警告信号:
while (!stream.DataAvailable)
{
}
正确的阅读方式是直接调用Read
。您需要使用 Read
中的 return 值来查看已到达的字节数。修剪零是不正确的(你不能那样接收零)和一个 hack,再次,应该在精神上发出危险信号!这不是正确的做法。
套接字很难正确。不要进行可疑的黑客攻击,这只会增加不确定性故障的可能性。
所以我通过深入研究 NetworkStream class 设法解决了这个问题。在 BeginReceiveTcpClient 的回调中,我从 tcpclient 中提取了网络流,因此我可以访问 BeginReceive 异步方法。相关代码如下:
private void ClientConnected(IAsyncResult ar)
{
byte[] readBytes = new byte[65536];
TcpClient client;
try
{
client = listener.EndAcceptTcpClient(ar);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
return;
}
try
{
NetworkStream stream = client.GetStream();
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
private void ReadStream(IAsyncResult ar)
{
try
{
NetworkStream stream = (NetworkStream)ar.AsyncState;
int bytesRead = stream.EndRead(ar);
content += Encoding.ASCII.GetString(buffer, 0, bytesRead);
dataProcessor.ProcessData(messages);
stream.BeginRead(buffer, 0, buffer.Length, ReadStream, stream);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}