第一个TCP响应接收0个字节,但根据netmon,之后会有响应

时间:2017-11-15 12:33:27

标签: c# tcp

我遇到的情况是我正在向机器发送正确的请求字节。当通过另一个应用程序运行时,我可以看到响应被发送,机器发送第一个不包含字节的响应(只有标题数据)所以在我的代码中我正在检查是否" 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());
        }
    }
}

}

1 个答案:

答案 0 :(得分:2)

这里的问题正是您正在检查tcpStream.DataAvailable。这是本地缓存的数据量,它为零会告诉您没有即将到达的内容。更典型的循环是:

while((numberOfBytesRead = tcpStream.Read(myReadBuffer, 0, myReadBuffer.Length)) > 0)
{ ... }

DataAvailable的唯一真正用途是决定是同步还是异步读取 - 如果缓冲区中没有任何内容,您可以选择异步读取。

注意一般你也应该非常小心“框架”并知道你在缓冲区中的内容是否可以被合理处理;因为你正在使用ASCII,所以只是在你的情况下侥幸逃脱它,但如果这是像UTF8那样你需要更加小心,作为一个单个字符可能跨越两个(或更多,理论上)Read调用 - 这意味着您可能在缓冲区末尾获得一个3字节字符的字节,并在开始时获得该相同字符的另外两个字节下一次Read电话中的缓冲区。