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

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

发送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); 

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

看到这个使用这种方法的答案 。

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

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

这里有完整的MSDN文档

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