类似的问题: C# Socket BeginReceive / EndReceive capturing multiple messages
我目前正在管理网站和winform应用程序之间的通信,这是通过以这种方式创建的websocket来完成的:
Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
如果该emmitter发送两个消息A([TagBeginMessage:lengthMessageA] aaaaaaaaaaaaaaaa [EndMessage])和B([TagBeginMessage:lengthMessageB] bbbbbbbbbbbbbbbbbbb [EndMessage]),我期望接收机将得到
[TagBeginMessage:lengthMessageA] aaaaaaaaaaaaaaaa [EndMessage] [TagBeginMessage:lengthMessageB] bbbbbbbbbbbbbbbbbbb [EndMessage]
或
[TagBeginMessage:lengthMessageB] bbbbbbbbbbbbbbbbbbb [EndMessage] [TagBeginMessage:lengthMessageA] aaaaaaaaaaaaaaaa [EndMessage]
对于绝大多数消息来说确实如此,但是当消息A很长并且消息B非常短时,接收的必要异步性质有时会导致错误,其中接收者得到这个:
[TagBeginMessage:lengthMessageA] aaaaaaaaaa [TagBeginMessageB:lengthMessageB] bbbbbbbbbbbbbbbbbbb [EndMessage] aaaaaa [EndMessageA]
虽然它需要每条消息的唯一结尾,但仍然可以对其进行解析。但是,虽然我没有看到它,但我担心这意味着以下情况也是可能的(由于套接字通过数据包发送数据):
[TagBeginMessage:lengthMessageA] aaaaa [TagBeginMessageB:lengthMessageB] bbbbbbaaaabbbbbbbbbbbbb [EndMessage] aaaaaa [EndMessageA]
这是不可解析的。在消息开头添加长度(如http://blog.stephencleary.com/2009/04/sample-code-length-prefix-message.html中所示)表示问题但未解决。我该怎么做才能避免这种情况?
我目前的解决方案是:
答案 0 :(得分:3)
听起来您正在同时从多个线程向同一连接发送数据。没问题,但如果你这样做,请确保在发送逻辑包(长度+数据)的过程中锁定与当前线程的连接 - 这样你就会收到一个完整的数据包(从一个发送线程)在接收不同线程发送的任何内容之前。
在TCP / IP下,保证包的顺序与它们发送的顺序相同,但如果你从一个线程发送半个逻辑包(长度+数据),然后从另一个线程发送半个包,那么协议层或接收端无法知道这一点。
答案 1 :(得分:2)
您已经链接到Stephen Cleary的博客,因此您知道tcp要求您进行某种形式的消息框架。 Here is the another one of Cleary's posts that describe your problem.
简而言之,您必须构建tcp消息。你也应该永远不会看到你的最终,不可解决的例子。 Tcp将以正确的顺序发送您的所有数据。
答案 2 :(得分:0)
我不是插座专家,但我有一些经验。您可以做的是拆分正在发送的数据。假设您有一个非常长的字符串,其中包含以下内容:" AAAAAAAABBBBBBCCCCDDDDDEEE"。您可以做的不是一次性发送整个字符串通过套接字,而是发送所有A字符然后是B然后是C然后是D等。在用户收到消息之前,您可以将所有字符合并在一起。这只是一个想法。