即使数据可用,从端口读取信息也会等待

时间:2015-01-15 10:22:15

标签: c# .net sockets tcpclient networkstream

我在向套接字发送信息并收到回复时遇到问题。我有一个正确执行的演示程序,所以我知道它不是另一端客户端的问题。

发送requestData并且客户端正常运行并响应,但我的代码永远不会在读取响应中退出循环。

在我倾听之前,客户能否做出回应?我怎样才能确保我不会错过收到的消息?

            networkStream = tcpClient.GetStream();
            StreamWriter clientStreamWriter = new StreamWriter();
            clientStreamWriter.WriteLine(requestData);
            clientStreamWriter.Flush();

            // Continuously read data on the socket and if it is more than just a ping, read the response.
            StringBuilder sbReadBuffer = new StringBuilder();

            while (true)
            {
                String response = readresponse(timeoutOn30Seconds);

                if (response.Length > 1 && (!response.Contains("\r\n") || response.Contains(",")))
                {
                    break;
                }
            }

            sbReadBuffer.Append(received);

            return sbReadBuffer.ToString();

readResponse:

    private string readresponse(Boolean timeoutOn30Seconds)
    {
        // Get network stream.
        DateTime lastConTime = DateTime.Now;
        Int32 i = 0;

        // Start listening to stream.
        while (!networkStream.DataAvailable)
        {
            Log.W(".");
            // Only check every 10ms.
            Thread.Sleep(10);

            // If no response in 30mins stop listening and give an offline warning.
            if ((DateTime.Now - lastConTime).TotalSeconds > tcpClient.ReceiveTimeout)
            {
                received = "CLIENT NOT FOUND";

                return received;
            }

            // Only check if application online every 1s.
            if (i > 100)
            {
                if (Process.GetProcessesByName(ConfigurationManager.AppSettings["ClientName"]).FirstOrDefault() == null && Convert.ToInt32(ConfigurationManager.AppSettings["Device"]) != 680)
                {
                    received = "CLIENT NOT FOUND";

                    return received;
                }

                i = 0;
            }

            i++;
        }

        // If data has been writted to the buffer, read it out and assign output variable and return that string for length comparison.
        byte[] receiveBuffer = new byte[tcpClient.ReceiveBufferSize];
        Int32 receiveCount = networkStream.Read(receiveBuffer, 0, receiveBuffer.Length);
        received = new ASCIIEncoding().GetString(receiveBuffer, 0, receiveCount);

        return received;
    }

2 个答案:

答案 0 :(得分:2)

DataAvailable不是一个了解数据是否即将到来的好方法,尤其是在一个肯定比网络通信更快的while循环中。

更好的方法是使用Read方法(字节读取)知道数据可用的位置,进入定时循环;所以以这种方式改变你的状态(然后调整其他部分)

while (networkStream.Read(receiveBuffer, 0, receiveBuffer.Length) > 0)
    {
        Log.W(".");
        // Only check every 10ms.
        Thread.Sleep(10);

但如果可能的话,我更喜欢异步方法,因此当数据传入时,您的客户端会收到通知。

请参阅使用此类方法的this answer

基本上设置一个异步回调,将在数据到来时触发

public void StartListening() {
IPHostEntry ipHostInfo = Dns.Resolve(Dns.GetHostName());
IPEndPoint localEP = new IPEndPoint(ipHostInfo.AddressList[0],11000);

Console.WriteLine("Local address and port : {0}",localEP.ToString());

Socket listener = new Socket( localEP.Address.AddressFamily,
    SocketType.Stream, ProtocolType.Tcp );

try {
    listener.Bind(localEP);
    listener.Listen(10);

    while (true) {
        allDone.Reset();

        Console.WriteLine("Waiting for a connection...");
        listener.BeginAccept(
            new AsyncCallback(SocketListener.acceptCallback), 
            listener );

        allDone.WaitOne();
    }
} catch (Exception e) {
    Console.WriteLine(e.ToString());
}

Console.WriteLine( "Closing the listener...");
}

在那里你可以阅读你的数据

public static void acceptCallback(IAsyncResult ar) {
    // Get the socket that handles the client request.
    Socket listener = (Socket) ar.AsyncState;
    Socket handler = listener.EndAccept(ar);

    // Signal the main thread to continue.
    allDone.Set();

    // Create the state object.
    StateObject state = new StateObject();
    state.workSocket = handler;
    handler.BeginReceive( state.buffer, 0, StateObject.BufferSize, 0,
        new AsyncCallback(AsynchronousSocketListener.readCallback), state);
}

Here full MSDN documentation

答案 1 :(得分:0)

你没有在循环中读入。要清除DataAvailable标志,您必须从networkStream中读取。 样品用法: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable%28v=vs.100%29.aspx