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

问题描述:

我在向套接字发送信息和接收响应时遇到问题。我有一个正确执行的演示程序,所以我知道它不是另一端客户端的问题。即使数据可用,端口读取信息也会等待

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; 
    } 

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

+0

不幸的是,我无法改写的核心由于业务限制而导致的应用程序结构。有什么办法可以调整当前设置的工作吗? –

+0

我用另一个选项编辑我以前的答案 – Luca

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