即使数据可用,从端口读取信息也会等待
Reading information from a port waits even though data available
我在通过套接字发送信息和接收响应时遇到问题。我有一个运行正常的演示程序,所以我知道这不是另一端客户端的问题。
请求数据已发送,客户端正确操作并响应,但我的代码从未退出读取响应中的循环。
客户会不会在我倾听之前做出回应?我怎样才能确保我不会错过任何收到的消息?
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();
读取响应:
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;
}
你没有读入 while 循环。要清除 DataAvailable 标志,您必须从 networkStream 中读取。
示例用法:
http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable%28v=vs.100%29.aspx
DataAvailable 不是了解数据是否到来的好方法,尤其是在肯定比网络通信更快的 while 循环中。
一个更好的方法可能是使用Read方法(读取字节)来知道哪里有数据可用,进入一个定时循环;所以以这种方式改变你的while条件(然后调整其他部分)
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);
}
我在通过套接字发送信息和接收响应时遇到问题。我有一个运行正常的演示程序,所以我知道这不是另一端客户端的问题。
请求数据已发送,客户端正确操作并响应,但我的代码从未退出读取响应中的循环。
客户会不会在我倾听之前做出回应?我怎样才能确保我不会错过任何收到的消息?
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();
读取响应:
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;
}
你没有读入 while 循环。要清除 DataAvailable 标志,您必须从 networkStream 中读取。 示例用法: http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable%28v=vs.100%29.aspx
DataAvailable 不是了解数据是否到来的好方法,尤其是在肯定比网络通信更快的 while 循环中。
一个更好的方法可能是使用Read方法(读取字节)来知道哪里有数据可用,进入一个定时循环;所以以这种方式改变你的while条件(然后调整其他部分)
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);
}