【发布时间】: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