我遇到的情况是我正在向机器发送正确的请求字节。当通过另一个应用程序运行时,我可以看到响应被发送,机器发送第一个不包含字节的响应(只有标题数据)所以在我的代码中我正在检查是否" tcpStream.DataAvailable"它显然会回归" false"程序退出。
问题在于,第一个响应不是数据的位置......它在以下几个响应中。
所以基本上如何忽略第一个响应并等待2+响应中的数据?
这是我正在使用的代码片段:
byte[] myReadBuffer = new byte[1024];
StringBuilder myCompleteMessage = new StringBuilder();
int numberOfBytesRead = 0;
// Incoming message may be larger than the buffer size.
do
{
numberOfBytesRead = tcpStream.Read(myReadBuffer, 0, myReadBuffer.Length);
myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
}
while (tcpStream.DataAvailable);
更新:
我将代码更改为异步处理通信。这是新代码(仍然不起作用):
public class GetCellList
{
private ManualResetEvent connectDone = new ManualResetEvent(false);
private ManualResetEvent sendDone = new ManualResetEvent(false);
private ManualResetEvent receiveDone = new ManualResetEvent(false);
private string _serverIP;
private int _serverPort;
private StateObject _stateObject = new StateObject();
private static String response = String.Empty;
public GetCellList(string serverIP, int serverPort)
{
_serverIP = serverIP;
_serverPort = serverPort;
_stateObject.workSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(_serverIP), _serverPort);
StartClient(remoteEP);
}
private void StartClient(IPEndPoint remoteEndpoint)
{
try
{
_stateObject.workSocket.BeginConnect(remoteEndpoint,
new AsyncCallback(ConnectCallback), _stateObject.workSocket);
connectDone.WaitOne();
Send(_stateObject.workSocket, GetData());
sendDone.WaitOne();
Receive(_stateObject.workSocket);
receiveDone.WaitOne();
Console.WriteLine("Response received : {0}", response);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private byte[] GetData()
{
var requestString = "00 25 B4 CE 42 80 D4 81 D7 DD 44 37 08 00 45 00 00 43 06 27 00 00 80 06 00 00 0A D4 E2 4E 0A 68 3D CC 2E 12 04 01 4B 7A C8 7B FE 5C 2E F5 50 18 00 FF 35 8C 00 00 43 50 43 52 00 01 19 00 00 00 1B 00 00 00 02 00 00 00 00 00 00 00 1D 00 00 00 00".Replace(" ", "");
return Convertors.ConvertToByteArray(requestString);
}
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
Console.WriteLine("Socket connected to {0}",
client.RemoteEndPoint.ToString());
connectDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void Receive(Socket client)
{
try
{
StateObject state = new StateObject();
state.workSocket = client;
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void ReceiveCallback(IAsyncResult ar)
{
try
{
StateObject state = (StateObject)ar.AsyncState;
Socket client = state.workSocket;
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
client.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReceiveCallback), state);
}
else
{
if (state.sb.Length > 1)
{
response = state.sb.ToString();
}
receiveDone.Set();
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void Send(Socket client, byte[] byteData)
{
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
private void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
Console.WriteLine("Sent {0} bytes to server.", bytesSent);
sendDone.Set();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
}
答案 0 :(得分:2)
这里的问题正是您正在检查tcpStream.DataAvailable
。这是本地缓存的数据量,它为零会告诉您没有即将到达的内容。更典型的循环是:
while((numberOfBytesRead = tcpStream.Read(myReadBuffer, 0, myReadBuffer.Length)) > 0)
{ ... }
DataAvailable
的唯一真正用途是决定是同步还是异步读取 - 如果缓冲区中没有任何内容,您可以选择异步读取。
注意一般你也应该非常小心“框架”并知道你在缓冲区中的内容是否可以被合理处理;因为你正在使用ASCII,所以只是在你的情况下侥幸逃脱它,但如果这是像UTF8那样你需要更加小心,作为一个单个字符可能跨越两个(或更多,理论上)Read
调用 - 这意味着您可能在缓冲区末尾获得一个3字节字符的字节,并在开始时获得该相同字符的另外两个字节下一次Read
电话中的缓冲区。