【问题标题】:Not seeing all data received through TCP看不到通过 TCP 接收的所有数据
【发布时间】:2017-08-30 14:58:46
【问题描述】:

我正在尝试使用用作 TCP 客户端的套接字接收数据,但不知何故,WireShark 中显示的所有数据在我的代码中都不可用。

使用 WireShark,我可以看到传入的数据包,并且测试工具(不是我制作的)以我期望的方式显示数据。

当我在下面的示例中打印recData 的长度时,它与在 WireShark 中看到的数据长度相关,因此到目前为止一切似乎都很好。

但是,当我想将收到的消息显示为可读字符串(UTF-8 编码的 XML)时,我只能看到我期望的部分消息。

我使用的Socket

            private Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private byte[] _recieveBuffer = new byte[1024];

        public void Connect()
        {
            try
            {
                sock.Connect(new IPEndPoint(IPAddress.Parse(this.IpAddress), this.Port));
                sock.ReceiveBufferSize = _recieveBuffer.Length;
            }
            catch (Exception ex)
            { }

            sock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);

        }

        private void ReceiveCallback(IAsyncResult ar)
        {
            int received = sock.EndReceive(ar);

            if (received <= 0)
                return;

            byte[] recData = new byte[received];
            Buffer.BlockCopy(_recieveBuffer, 0, recData, 0, received);

            if (onDataReceived != null)
                onDataReceived(this, new MyNewEventargs(recData));

            Console.WriteLine(Encoding.UTF8.GetString(recData));

            sock.BeginReceive(_recieveBuffer, 0, _recieveBuffer.Length, SocketFlags.None, new AsyncCallback(ReceiveCallback), null);                
        }

我收到的数据包:

我注意到第二个收到的包裹(图中突出显示的那个)大约是第一个包裹的两倍。

当我查看包的内容时,我可以看到第一个包含 1 个完整的 XML 项,第二个包含 2 个。

但是,当我将第二个包的内容打印为字符串时,我仍然只能看到一个 XML 项,因此第三个丢失了。

我期望的完整 XML 消息如下所示:

<?xml version="1.0" standalone="yes"?>
<Xml>
<Element1 Attirbute1="First item" Attirbute2="0" Attirbute3="0" Attirbute4="0" Attirbute5="0">
    <Element2 Attirbute1="600" Attirbute2="1" Attirbute3="bla"/>
</Element1>
</Xml>
<?xml version="1.0" standalone="yes"?>
<Xml>
<Element1 Attirbute1="Second item" Attirbute2="0" Attirbute3="0" Attirbute4="0" Attirbute5="0">
    <Element2 Attirbute1="600" Attirbute2="1" Attirbute3="bla"/>
</Element1>
</Xml>
<?xml version="1.0" standalone="yes"?>
<Xml>
<Element1 Attirbute1="Third item" Attirbute2="0" Attirbute3="0" Attirbute4="0" Attirbute5="0">
    <Element2 Attirbute1="600" Attirbute2="1" Attirbute3="bla"/>
</Element1>
</Xml>

控制台显示的 XML 消息如下所示:

//First package
<?xml version="1.0" standalone="yes"?>
<Xml>
<Element1 Attirbute1="First item" Attirbute2="0" Attirbute3="0" Attirbute4="0" Attirbute5="0">
    <Element2 Attirbute1="600" Attirbute2="1" Attirbute3="bla"/>
</Element1>
</Xml>

//First item of second package
<?xml version="1.0" standalone="yes"?>
<Xml>
<Element1 Attirbute1="Second item" Attirbute2="0" Attirbute3="0" Attirbute4="0" Attirbute5="0">
    <Element2 Attirbute1="600" Attirbute2="1" Attirbute3="bla"/>
</Element1>
</Xml>

如您所见,第三个 XML 项丢失了。

我尝试使用线程和秒表来查看是否是时间问题,但由于收到的包裹的大小是正确的,我认为这不是我的问题的原因。

当我将收到的byte[] 打印到控制台时,我还没有进行任何反序列化。

我怎样才能让这个套接字接收(或让我看到)所有发送的数据?


编辑:

经过更多调试后,我发现我似乎确实获得了所有数据,但我认为 Encoding.UTF8.GetString(recData) 出了点问题。

第二次调用ReceiveCallback,接收到的字节数是446而不是221。数据被复制到byte[]recData,它确实保存了446个字节。当我在这一行设置断点并手动将 int received 更改为 221(因此它只会将第一项复制到 byte[])时,我得到的结果与它停留在 446 时的结果相同。

所以我确实得到了所有数据,但不知何故它没有解码成我期望的字符串。

希望这是有道理的..

【问题讨论】:

  • 我认为您的代码中存在竞争条件,如果您还在 ReceiveCallback 中接收数据,则不会触发对回调的另一个调用。
  • 可以显示发送方式吗?
  • @neuhaus 为什么? TCP 套接字有内部缓冲区。
  • @Jeroen van Langen 我无权访问服务器的源代码。
  • 他错过了最后一条消息,而不是第一条..所以它与事件处理程序没有任何关系。

标签: c# xml sockets networking tcp


【解决方案1】:

您的“onDataReceived”在做什么?有什么会影响你的逻辑吗?

您的代码在这里运行顺利(至少使用通用 HTML 进行测试),除了上面提到的事件处理程序之外,所有字节都接收并显示。

(注意:无法发布 cmets,这就是我发布回复的原因。请随意删除。)

C.

【讨论】:

  • 目前“OnDataReceived”仅反序列化消息并将其打印到文本框。当我删除它时,我只得到第一个包,当我使用thread.sleep(50); 进行测试时,我再次看到这两个包,如原始问题中所述。毕竟是时间问题吗?
  • 所以事件处理程序以某种方式改变了结果,也许数据本身是可疑的......也许你可以发布事件处理程序代码和收到的 2 个数据包的原始字节?
猜你喜欢
  • 2012-09-27
  • 2013-08-14
  • 1970-01-01
  • 2014-09-06
  • 1970-01-01
  • 2012-03-10
  • 2018-01-25
  • 2023-04-07
  • 2020-06-23
相关资源
最近更新 更多