TCP 接收没有 return 预期的字节数

TCP Receive does not return expected number of bytes

我使用 TCPIP 从控制器获取数据。当使用TCPIP接收数据时,我只能得到第一行数据,这意味着数据长度是1514,但另一行长度为174的数据无法从C#的TCPIP客户端协议中获取。可能需要你们就此提出建议。

下图是使用Wireshark跟踪TCPIP数据

下图是从TCPIP客户端协议接收数据的方法。

谢谢。

以下是我如何通过 TCPIP 连接和获取数据。如有错误请指正

public void Connect(string ipAddress, int port)
    {
        lock (this)
        {
            try
            {
                IPAdddress = ipAddress;
                Port = port;
                IPAddress ip = IPAddress.Parse(ipAddress);
                IPEndPoint endPoint = new IPEndPoint(ip, port);

                Client.BeginConnect(endPoint, new AsyncCallback(OnClientConnected), null);
            }
            catch (Exception ex)
            {
                ExceptionThrownEventArgs args = new ExceptionThrownEventArgs();
                args.Exception = ex;
                
                if (m_ExceptionThrown != null)
                {
                    foreach (Delegate del in m_ExceptionThrown.GetInvocationList())
                    {
                        ISynchronizeInvoke syncer = del.Target as ISynchronizeInvoke;
                        if (syncer == null)
                        {
                            del.DynamicInvoke(this, args);
                        }
                        else
                        {
                            syncer.BeginInvoke(del, new object[] { this, args });
                        }
                    }
                    #endregion
                }

                // SupportMethod.ShowExceptionMessage(ex, Output.EventLog);
            }
        }
    }

private void OnMessageReceived(IAsyncResult result)
    {
        try
        {           
            Metadata metadata = (Metadata)result.AsyncState;

            if (metadata.ReceiveBuf[0] == 0)
            {
                Disconnect();
            }
            else
            {
                Client.EndReceive(result);
 
                
                var e = Encoding.GetEncoding("iso-8859-1");
                LastMessageReceived = e.GetString(metadata.ReceiveBuf).Trim('[=11=]');
                Debug.Print("TCPRaw: " + LastMessageReceived);
                
                if (m_EchoOnReceived)
                {                        
                    Echo(LastMessageReceived);
                }
               
                MessageReceivedEventArgs args = new MessageReceivedEventArgs();
                if (m_MessageReceived != null)
                {
                    #region Fire the MessageReceived event (bound during instantiation of ClientSocket).
                    
                    foreach (Delegate del in m_MessageReceived.GetInvocationList())
                    {
                        ISynchronizeInvoke syncer = del.Target as ISynchronizeInvoke;
                        if (syncer == null)
                        {
                            del.DynamicInvoke(this, args);
                        }
                        else
                        {
                            syncer.BeginInvoke(del, new object[] { this, args });
                        }
                    }
                    #endregion
                }

                // Provide additional data for the socket operation. Re-instantiate a new Metadata object.
                metadata = new Metadata();
                metadata.ReceiveBuf = new byte[m_ReceiveBufSize];

                // Continue to prepare receive data from the connected Server.
                Client.BeginReceive(
                    metadata.ReceiveBuf,
                    0,
                    metadata.ReceiveBuf.Length,
                    SocketFlags.None,
                    new AsyncCallback(OnMessageReceived),
                    metadata);
            }
        }
        catch (Exception ex)
        {
            ExceptionThrownEventArgs args = new ExceptionThrownEventArgs();
            args.Exception = ex;

            
            // ExceptionThrown Event.
            if (m_ExceptionThrown != null)
            {
                #region Fire the ExceptionThrown event (bound during instantiation of ClientSocket).
                // Check the Target of each delegate in the event's invocation list, and marshal the call
                // to the target thread if that target is ISynchronizeInvoke
                // ref: 

                foreach (Delegate del in m_ExceptionThrown.GetInvocationList())
                {
                    ISynchronizeInvoke syncer = del.Target as ISynchronizeInvoke;
                    if (syncer == null)
                    {
                        del.DynamicInvoke(this, args);
                    }
                    else
                    {
                        syncer.BeginInvoke(del, new object[] { this, args });
                    }
                }
                #endregion
            }

            //  SupportMethod.ShowExceptionMessage(ex, Output.EventLog);
        }
    }

对于TCP/IP,当你在Receive方法中指定接收的字节数时,它是一个上限,而不是绝对字节数。如果您收到的字节数少于请求的字节数,则需要进行另一次读取并将结果组合成您想要的数据。这就是为什么 Receive 方法允许您在数组中指定索引以放置接收到的数据。例如:

var message = new byte[myMessageSize];
var totalBytesReceived = 0;
while (totalBytesReceived < myMessageSize)
{
    var bytesReceived = socket.Receive(message, 
                                       totalBytesReceived, 
                                       myMessageSize - totalBytesReceived,
                                       SocketFlags.None);
    
    totalBytesReceived += bytesReceived;
}

我建议不要使用 BeginReceive,回调很难管理,而且大多数人都做错了。使用同步方法或 ReceiveAsync()。