c#socket多个数据包堆栈

Kel*_*ton 1 c# sockets

我在c#中使用套接字时遇到问题.这是一个例子.假设我发送数字1,然后我立即发送数字2.我遇到的问题有时是应该接收它的客户端将收到包含'12'的数据包.我想知道是否有内置的方法来区分数据包而不使用字符或东西来分离数据.

再说一遍,我说了两个包.一个数字为'1',一个数字为'2'.服务器接收数据为"12"的1个数据包.我不想将数据包与字符分开,例如':1 :: 2:'或类似的东西,因为我并不总是能控制传入数据的格式.

有任何想法吗?

就像我这样做

client.Send(new byte[1]{'1'}, 1,SocketFlags.None);
client.Send(new byte[1]{'2'}, 1,SocketFlags.None);
Run Code Online (Sandbox Code Playgroud)

然后在服务器端

byte[] data = new byte[1024];
client.Receive(data);
Run Code Online (Sandbox Code Playgroud)

即使我做两个单独的发送,数据有时会以"12"返回.

mek*_*ian 5

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

TCP接收窗口大小和缩放@ MSDN

虽然在示例中您已经在接收端观察到1个包含2个字节的统一blob数据,但是可以接收1个字节乘1个字节的序列(由发送方发送),具体取决于网络条件以及许多可能的组合如果您正在执行非阻塞读取,则读取0,1和2字节.在典型的非拥塞LAN或环回设置上进行调试时,如果发送端没有延迟,您几乎不会看到这一点.在网络堆栈的较低级别,有一些方法可以检测每个数据包的传输,但它们不会用于典型的TCP编程,并且不在应用范围内.

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

您应该考虑分隔数据或找到其他方法来检测何时到达应用程序定义的数据单元的末尾,并坚持使用TCP.


Ste*_*ary 5

TCP/IP工作在一个抽象,没有一个数据包的抽象.

当你打电话时Send,你没有发送数据包.您只是将字节附加到流.

通话时Receive,您没有收到数据包.您只从流中接收字节.

因此,必须定义"消息"的开始和结束位置.只有三种可能的解决方案:

  1. 每条消息都具有已知大小(例如,所有消息都是42字节).在这种情况下,您只需保留Receive数据,直到获得那么多字节.
  2. 使用您已经知道的分隔符.
  3. 使用长度前缀(例如,为每条消息添加4字节长度的消息前缀).在这种情况下,您保持Receive长度前缀直到它到达,解码它以获得消息的实际长度,然后保持Receive消息本身.

你必须自己做消息框架.TCP/IP无法为您完成.