从套接字接收的流是否仅限于单个发送命令? [英] Is the received stream from a socket limited to a single send command?

查看:16
本文介绍了从套接字接收的流是否仅限于单个发送命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在开发一个多线程应用程序,我使用以下(简化)代码接收数据:

private void BeginReceiveCallback(IAsyncResult ar){bytesReceived = this.Socket.EndReceive(ar);byte[] receivedData = new byte[bytesReceived];Array.Copy(buffer, receivedData, bytesReceived);长协议长度 = BitConverter.ToInt64(receivedData, 0);字符串协议 = Encoding.ASCII.GetString(receivedData, 8, (int)protocolLength);IList<对象>发送对象 =ParseObjectsFromNetworkStream(receivedData, 8 + protocolLength);InvokeDataReceived(protocol, sentObjects);}

我发现 receivedData 不仅包含预期数据,还包含更多数据.我怀疑这是后来发送的数据,它与流中的前一个数据混合在一起.

我的问题是,我可以期望将哪些数据存储在此缓冲区中.它可以包含来自客户端的两个不同发送操作的数据吗?在这种情况下,我想我必须想出一个协议来区分从客户端发送的数据消息".一种简单的方法是分别以特定(唯一)字节开始和结束每个流.有没有一种通用的方法来分隔消息?此外,我想这意味着单个接收调用可能不足以从客户端获取所有数据,这意味着我必须循环直到找到结束字节?

解决方案

TCP/IP 套接字连接由两个独立的流组成:一个传入和一个传出.

这是经常被忽略的 TCP/IP 的关键概念之一.从应用程序的角度来看,TCP/IP 不对数据包进行操作;它在流上运行!

没有发送数据包的方法.API 根本不存在.当您发送数据时,您只需将这些字节放在传出流中.然后从另一端的传入流中读取它们.

例如,一侧可以发送 5 个字节,然后再发送另外 5 个字节.接收端可以接收两批5个字节,或者一次一个,或者一次读取全部10个...

要将传入的字节流拆分为消息,您需要消息框架.通常使用两种解决方案之一.您建议的一种是 delimiter 解决方案,其中 SOT/EOT 字节用于指定消息边界.另一种(我更喜欢)是 length prefix 解决方案,其中消息的长度是消息本身的前缀.

在我的博客上进行了更深入的讨论,以及长度前缀示例代码.p>

I currently work on a multithreaded application where I receive data using the following (simplified) code:

private void BeginReceiveCallback(IAsyncResult ar)
{
bytesReceived = this.Socket.EndReceive(ar);
byte[] receivedData = new byte[bytesReceived];
Array.Copy(buffer, receivedData, bytesReceived);

long protocolLength = BitConverter.ToInt64(receivedData, 0);
string protocol = Encoding.ASCII.GetString(receivedData, 8, (int)protocolLength);
IList<object> sentObjects = 
ParseObjectsFromNetworkStream(receivedData, 8 + protocolLength);

InvokeDataReceived(protocol, sentObjects);
}

I'm experiencing that receivedData contains not only the expected data, but also a lot more. I suspect that this is data sent afterwards that has been mixed in with the previous in the stream.

My question is, what data can I expect to be stored in this buffer. Can it contain data from two different send operations from the client side? In this case, then I suppose I will have to come up with a protocol that can differentiate between the data 'messages' sent from the client side. A simple approach would be to respectively start and end each stream with a specific (unique) byte. Is there a common approach to seperating messages? Furthermore I guess this means that a single receive call might not be enough to get all the data from the client which means I'll have to loop until the end byte was found?

解决方案

TCP/IP socket connections consist of two independent streams: one incoming and one outgoing.

This is one of the key concepts of TCP/IP that is often missed. From the perspective of the application, TCP/IP does not operate on packets; it operates on streams!

There is no method to send a packet. The API simply does not exist. When you send data, you just place those bytes in the outgoing stream. They are then read from the incoming stream on the other side.

As an example, one side can send 5 bytes and then send another 5 bytes. The receiving side can receive two batches of 5 bytes, or one at a time, or all 10 in a single read...

To split the incoming stream of bytes into messages, you need message framing. One of two solutions is commonly used. The one you suggested is the delimiter solution, where SOT/EOT bytes are used to designate message boundaries. Another one (which I prefer) is the length prefix solution, where the length of the message is prefixed to the message itself.

A more thorough discussion is on my blog, along with sample code for length prefixing.

这篇关于从套接字接收的流是否仅限于单个发送命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆