动态输入数据时 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);
        }
    }