【发布时间】:2014-04-09 22:15:52
【问题描述】:
嗯,对我来说,数据包碎片化是如何发生的似乎很模糊,因为我的本地测试从来没有发生过这种情况,而且我不知道在通知我的应用程序我实际上收到了一些信息之前要如何处理碎片化的数据包。
这是我从连接的客户端套接字接收的方式
var asynchronousState = (AsynchronousState) ar.AsyncState; // AsynchronousState is an entity that Holds each connected socket's Buffer, IPEndPoint and so on...
try {
Socket socket = asynchronousState.Socket;
int length = socket.EndReceive(ar);
if (0 != length) {
if (null != ClientReceive) {
var bytes = new byte[length];
Array.Copy(asynchronousState.Buffer, bytes, length);
ClientReceive(asynchronousState, bytes);
Array.Clear(asynchronousState.Buffer, 0, asynchronousState.Buffer.Length);
}
if (socket.Connected) {
socket.BeginReceive(asynchronousState.Buffer, 0, asynchronousState.Buffer.Length, SocketFlags.None, HandleAsyncReceive, asynchronousState);
return;
}
}
DisposeSocket(asynchronousState);
}
catch (SocketException exception) {
if (exception.SocketErrorCode != SocketError.Disconnecting &&
exception.SocketErrorCode != SocketError.NotConnected &&
exception.SocketErrorCode != SocketError.ConnectionReset &&
exception.SocketErrorCode != SocketError.ConnectionAborted &&
exception.SocketErrorCode != SocketError.Shutdown) {
Console.WriteLine(exception);
Core.Logger.Log(exception);
}
DisposeSocket(asynchronousState);
}
我如何构建我的数据包
public class ExchangeMessage : PacketStructure //Packet Structure is a custom builder similar to `BinaryWrite/Reader` : This returns a byte[] or builds from a byte[]
{
public int Length;
public int Type;
public byte[] PublicKey
{
get { return ReadArray(140, 4); }
set { WriteArray(value, 4); }
}
public ExchangeMessage(byte[] receivedPacket) : base(receivedPacket) {}
public ExchangeMessage(int length, int type) : base(length, type)
{
Length = length;
Type = type;
}
}
现在,每当我收到期望应用程序能够反序列化或重建我的 Packet 的东西时,我都会调用 ClientReceive 事件处理程序。 What if the packet was fragmented ?
我很困惑,因为通过研究这个主题,我发现其中有很多不同的意见,我对此表示怀疑 If you are building your Packet by yourself, it will not be fragmented!
【问题讨论】:
-
1) TCP 不使用数据包。您可能对 UDP 感到困惑。 2) 如果您在 TCP 之上构建数据包,您将必须意识到您不会一次获得整个数据包。您将需要有长度字段等来重建数据包。
-
@BobDalgleish:所以我应该将套接字类型更改为 UDP,我很高兴吗?我使用 TCP 是否应该再次调用 EndReceive 以获取更多发送的数据?或者如何处理这种行为?对不起,我完全一无所知。
-
@Bob:当然 TCP 使用数据包。我认为您的意思是边界不会保留给用户。
-
阅读此相关问题clientStream.Read returns wrong number of bytes。对于二进制数据,我建议写出每条消息的长度,然后循环读取,直到收到完整的消息。
-
@Loki:这与发生在 IP 层的数据包碎片无关。