c#套接字多数据包堆栈

c#套接字多数据包堆栈,c#,sockets,C#,Sockets,我在c#中使用套接字时遇到问题。这里有一个例子。假设我发送数字1,然后我立即发送数字2。我有时遇到的问题是,本应接收它的客户端将接收包含“12”的数据包。我想知道是否有一种内置的方法可以在不使用字符或其他东西来分隔数据包的情况下区分数据包 再总结一下,我说了两包。一个是数字“1”,一个是数字“2”。 服务器接收到1个数据包,其中包含数据“12”。 我不想用字符分隔数据包,如“:1::2:”或诸如此类的内容,因为我并不总是能够控制传入数据的格式 有什么想法吗 就像我这样做一样 client.Sen

我在c#中使用套接字时遇到问题。这里有一个例子。假设我发送数字1,然后我立即发送数字2。我有时遇到的问题是,本应接收它的客户端将接收包含“12”的数据包。我想知道是否有一种内置的方法可以在不使用字符或其他东西来分隔数据包的情况下区分数据包

再总结一下,我说了两包。一个是数字“1”,一个是数字“2”。 服务器接收到1个数据包,其中包含数据“12”。 我不想用字符分隔数据包,如“:1::2:”或诸如此类的内容,因为我并不总是能够控制传入数据的格式

有什么想法吗

就像我这样做一样

client.Send(new byte[1]{'1'}, 1,SocketFlags.None);
client.Send(new byte[1]{'2'}, 1,SocketFlags.None);
然后在服务器端

byte[] data = new byte[1024];
client.Receive(data);

数据有时会返回“12”,即使我分别发送了两次。

在不知道上下文的情况下很难回答您的问题。相反,默认情况下,TCP/IP自动为您处理数据包管理(尽管您以基于流的方式接收数据包)。但是,当您有一个非常特定的(糟糕的?)实现时,您可以同时通过一个套接字发送多个流,这使得较低级别的TCP/IP无法检测到差异。因此,您很难在客户机上识别不同的流。唯一的解决方案是发送2个完全唯一的流(例如,流1只发送低于127的字节,流2只发送高于或等于127的字节)。再说一次,这是一种可怕的行为

在不了解上下文的情况下很难回答你的问题。相反,默认情况下,TCP/IP自动为您处理数据包管理(尽管您以基于流的方式接收数据包)。但是,当您有一个非常特定的(糟糕的?)实现时,您可以同时通过一个套接字发送多个流,这使得较低级别的TCP/IP无法检测到差异。因此,您很难在客户机上识别不同的流。唯一的解决方案是发送2个完全唯一的流(例如,流1只发送低于127的字节,流2只发送高于或等于127的字节)。同样,这是一种可怕的行为

TCP是一种流协议,因此您将始终接收自上次读取以来到达的任何数据,直到接收方端的流窗口大小。该缓冲区可以填充从发送方发送的任意给定大小的多个数据包接收的数据

尽管您在示例中观察到接收端有1个包含2个字节的统一数据块,但根据网络条件,以及进行非阻塞读取时0、1和2字节读取的许多可能组合,可以接收1字节接1字节的序列(由发送方发送)。在典型的无阻塞LAN或环回设置上进行调试时,如果发送端没有延迟,您几乎永远不会看到这种情况。在网络堆栈的较低级别,有一些方法可以检测每个数据包的传输,但它们不用于典型的TCP编程,并且超出了应用范围

如果您切换到UDP,那么每个数据包都将在发送时接收,这将符合您的期望。这可能更适合您,但请记住,UDP没有传递承诺,网络路由可能会导致数据包无序传递


您应该研究如何界定数据或找到其他方法来检测您何时到达应用程序定义的数据单元的末尾,并坚持使用TCP。

TCP是一种流协议,因此您将始终接收自上次读取以来到达的任何数据,直到接收方端的流窗口大小。该缓冲区可以填充从发送方发送的任意给定大小的多个数据包接收的数据

尽管您在示例中观察到接收端有1个包含2个字节的统一数据块,但根据网络条件,以及进行非阻塞读取时0、1和2字节读取的许多可能组合,可以接收1字节接1字节的序列(由发送方发送)。在典型的无阻塞LAN或环回设置上进行调试时,如果发送端没有延迟,您几乎永远不会看到这种情况。在网络堆栈的较低级别,有一些方法可以检测每个数据包的传输,但它们不用于典型的TCP编程,并且超出了应用范围

如果您切换到UDP,那么每个数据包都将在发送时接收,这将符合您的期望。这可能更适合您,但请记住,UDP没有传递承诺,网络路由可能会导致数据包无序传递


您应该研究数据定界或寻找其他方法来检测您何时到达应用程序定义的数据单元的末尾,并坚持使用TCP。

您必须在TCP消息定界符中输入数据,或使用字节计数来判断一条消息从何处开始,另一条消息从何处开始

您的代码还有一个严重错误。TCP套接字可能不会在一次呼叫中为您提供所有要接收的数据。您必须在接收数据时循环,直到数据流中特定于应用程序的记录表明已接收到整个消息。您对client.Receive(data)的调用返回接收的字节数。你应该抓住那个数字

同样,当您发送数据时,可能不会在一次调用中发送所有数据。您必须在发送数据时循环,直到发送的字节数等于您要发送的字节数。调用client.Send返回实际发送的字节数,这可能不是您尝试发送的全部字节数

我看到人们在使用套接字时最常见的错误是,他们不会在发送和接收时循环。如果您理解为什么需要执行循环,那么您就知道为什么需要使用分隔符或字节计数。

您必须将