我正在研究什么应该是一个简单的TCP服务器应用程序,它从流中接收数据并将其存储在列表中。
每个连接在一条消息中发送数据时,我已成功获取数据。我的问题似乎是从命令行使用telnet测试它。我将开始输入,程序将根据我的打字速度获取一个或两个字符,然后不再从该流中接收任何内容。我真的很不知道为什么。如果我在stream.DataAvailable循环中放入一个thread.sleep,那么它将获得更多的字符但是会再次停止。任何帮助表示赞赏。我的课程如下:
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('\0');
}
if (message != null)
{
messages.Add(message);
message = "";
}
listener.BeginAcceptTcpClient(ClientConnected, listener);
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
}
}
public void Stop()
{
listener.Stop();
}
}
答案 0 :(得分:2)
读取循环非常不正确。
您误解了DataAvailable
没有告诉您将到达多少字节。它给你一个下限,可以随时说0。循环将提前中止。使用DataAvailable
几乎总是不正确的。
这没有任何结果,是一个忙碌的等待,应该与你举起一个红旗:
while (!stream.DataAvailable)
{
}
正确的阅读方式是简单地拨打Read
。您需要使用Read
的返回值来查看已到达的字节数。修剪零是不正确的(你不能以这种方式接收零)和一个再次应该引发精神红旗的黑客!这可能是正确的做法。
套接字很难做到。不要制造可疑的黑客行为,只会增加非确定性失败的可能性。
答案 1 :(得分:0)
所以我设法通过更多地查看NetworkStream类来解决这个问题。在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);
}
}