Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 处理TCP数据包碎片_C#_Sockets - Fatal编程技术网

C# 处理TCP数据包碎片

C# 处理TCP数据包碎片,c#,sockets,C#,Sockets,对我来说,数据包碎片是如何发生的似乎很模糊,因为我的本地测试从未发生过这种情况,在通知我的应用程序我实际收到了一些信息之前,我不知道如何处理碎片数据包 下面是我从连接的客户端套接字接收数据的方式 var asynchronousState = (AsynchronousState) ar.AsyncState; // AsynchronousState is an entity that Holds each connected socket's Buffer, IPEndPoint and s

对我来说,数据包碎片是如何发生的似乎很模糊,因为我的本地测试从未发生过这种情况,在通知我的应用程序我实际收到了一些信息之前,我不知道如何处理碎片数据包

下面是我从连接的客户端套接字接收数据的方式

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;
    }
}
现在,每当我收到希望应用程序能够反序列化或重新生成数据包的内容时,我都会调用
ClientReceive
事件处理程序<代码>如果数据包被碎片化怎么办?


我非常困惑,因为通过研究这个主题,我发现其中有很多不同的观点,我对此表示怀疑,即
如果您自己构建数据包,它将不会被分割

套接字API不会向您提供数据包片段,只提供完整的数据包。TCP/IP堆栈将缓冲接收到的片段,直到它有一个完整的数据包,如果一些片段丢失,整个数据包将被丢弃,并且必须全部重新传输

这是路径MTU检测提高性能的一个原因——它可以防止中间通道碎片和相应的数据包错误率增加。发送较小的数据包将导致同样多的错误,但整个丢失的数据包可以通过选择性ACK进行处理,这比丢弃部分数据包的接收片段更有效

如果您使用较低级别的网络API,您可能会看到数据包片段


请注意,TCP数据包与
send()
调用不以1:1对应。Nagle算法可以将多个写入合并到一个数据包中,大于路径MTU的单个写入将生成多个数据包。我想这就是鲍勃在评论中提到的


碎片、数据包丢失和重传都在TCP/IP内部处理。您的应用程序不需要担心它。应用程序应将TCP套接字视为字节流

输入的字节以相同的顺序输出。需要多长时间以及有多少人一次出来并不能保证,这超出了你的控制范围

由于您希望将数据视为具有结构,而不仅仅是字节,因此必须自己添加该结构。长度前缀和记录分隔符都是执行此操作的常用方法

例如,HTTP对命令/响应和元数据使用记录分隔符。HTTP命令和所有头由
\r\n
分隔。缺点是,如果分隔符出现在数据中,则需要对其进行转义

HTTP/1.1200正常
日期:2005年5月23日星期一格林尼治标准时间22:38:34
服务器:Apache/1.3.3.7(Unix)(Red Hat/Linux)
最后修改:周三,2003年1月8日23:11:55格林尼治标准时间
ETag:“3f80f-1b6-3e1cb03b”
内容类型:text/html;字符集=UTF-8
内容长度:131
接受范围:字节
连接:关闭
示例页
你好,世界,这是一个非常简单的HTML文档。

还使用长度前缀。
内容长度
标题给出有效负载的长度。这允许任何字节出现在有效负载中。

套接字API不会提供数据包片段,只提供完整的数据包。TCP/IP堆栈将缓冲接收到的片段,直到它有一个完整的数据包,如果一些片段丢失,整个数据包将被丢弃,并且必须全部重新传输

这是路径MTU检测提高性能的一个原因——它可以防止中间通道碎片和相应的数据包错误率增加。发送较小的数据包将导致同样多的错误,但整个丢失的数据包可以通过选择性ACK进行处理,这比丢弃部分数据包的接收片段更有效

如果您使用较低级别的网络API,您可能会看到数据包片段


请注意,TCP数据包与
send()
调用不以1:1对应。Nagle算法可以将多个写入合并到一个数据包中,大于路径MTU的单个写入将生成多个数据包。我想这就是鲍勃在评论中提到的


碎片、数据包丢失和重传都在TCP/IP内部处理。您的应用程序不需要担心它。应用程序应将TCP套接字视为字节流

输入的字节以相同的顺序输出。需要多长时间以及有多少人一次出来并不能保证,这超出了你的控制范围

由于您希望将数据视为具有结构,而不仅仅是字节,因此必须自己添加该结构。长度前缀和记录分隔符都是执行此操作的常用方法

例如,HTTP对命令/响应和元数据使用记录分隔符。HTTP命令和所有头由
\r\n
分隔。缺点是,如果分隔符出现在数据中,则需要对其进行转义

HTTP/1.1200正常
日期:2005年5月23日星期一格林尼治标准时间22:38:34
服务器:Apache/1.3.3.7(Unix)(Red Hat/Linux)
最后修改:周三,2003年1月8日23:11:55格林尼治标准时间
ETag:“3f80f-1b6-3e1cb03b”
内容类型:text/html;字符集=UTF-8
内容长度:131
接受范围:字节
连接:关闭
示例页
你好,世界,这是一个非常简单的HTML文档。

还使用长度前缀。
内容长度
标题给出有效负载的长度。这允许任何字节出现在有效负载中。

1)TCP不使用数据包。您可能会与UDP混淆。2) 如果您是在TCP之上构建数据包,那么您必须意识到,您不会一次获得整个数据包。您需要有长度字段等来重建数据包。@BobDalgleish:所以我应该将套接字类型更改为UDP,然后我就可以开始了吗?我应该使用TCP再次调用EndReceive来获取更多发送的数据吗?或者如何处理suc
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
ETag: "3f80f-1b6-3e1cb03b"
Content-Type: text/html; charset=UTF-8
Content-Length: 131
Accept-Ranges: bytes
Connection: close

<html>
<head>
  <title>An Example Page</title>
</head>
<body>
  Hello World, this is a very simple HTML document.
</body>
</html>