动态输入数据时,TCP服务器无法正确接收

时间:2016-02-02 15:58:59

标签: c# tcp .net-4.0 tcpclient networkstream

我正在研究什么应该是一个简单的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();
    }

}

2 个答案:

答案 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);
        }
    }