SocketAsyncEventArgs 和缓冲,而消息是在部分

Posted

技术标签:

【中文标题】SocketAsyncEventArgs 和缓冲,而消息是在部分【英文标题】:SocketAsyncEventArgs and buffering while messages are in parts 【发布时间】:2010-05-24 13:42:52 【问题描述】:

C# 套接字服务器,它有大约 200 - 500 个活动连接,每个连接都不断地向我们的服务器发送消息。

大约 70% 的时间消息处理得很好(以正确的顺序等),但是在其他 30% 的情况下,我们将消息弄乱了,事情就搞砸了。我们应该注意到,一些客户端以 unicode 格式发送数据,而另一些则以 ASCII 格式发送数据,因此也可以处理。

发送到服务器的消息是一个可变长度的字符串,以 char3 结尾,这是我们中断的 char3,除了我们不断接收数据。

谁能解释一下我们的 ProcessReceive 代码,看看是什么可能导致我们出现问题,以及我们如何解决这个小问题(希望这是一个小问题!)

代码如下:

【问题讨论】:

此处代码:95.131.67.163/code.txt 【参考方案1】:

首先,我相信你知道,但它总是值得重复; TCP 是字节流。它对您可能确定存在于该字节流中的任何应用程序级别的“消息”一无所知。所有成功的套接字 Recv 调用,无论是同步还是异步,都可以返回介于 1 和提供的缓冲区大小之间的任意字节数。

考虑到这一点,您应该在做任何其他事情之前真正处理您的消息框架(即寻找您的分隔符)。如果您没有找到分隔符,则只需使用相同的SocketAsyncEventArgs、相同的缓冲区重新发出读取并将偏移量设置为您当前所在的位置,这会将更多数据读取到缓冲区中,您可以再次查找下一次读取完成后的分隔符...理想情况下,您会在此缓冲区中搜索分隔符时跟踪上次到达的位置,以减少重复扫描...

现在你没有这样做,如果你收到一条消息,你可能会引用消息中的任何字节,如果消息被拆分为多次读取,那么你对e.Buffer[e.Offset] == 255 的使用将失败。

【讨论】:

e.Buffer[e.Offset] = 255 纯粹是为了指示客户端是否运行 unicode 客户端,我们只对 255 作为客户端发送的第一条消息感兴趣,然后我们在他们的状态对象中设置 isUnicode 并从那时起使用它。分隔符是我们在将内容附加到 states sb 字符串后首先检查的 (char3)。这有点奇怪,因为 80% 的时间它都没有问题,但是当我们注销错误时,我们发现找到了 char3 但字符串从一开始就不完整。那是没有意义的部分 事实上,似乎大多数消息都预先附加了一堆问号。听起来像一个 unicode 错误,但也不确定发生在哪里 例如:??????????????????????????????????3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e 是一个消息混乱,应该是:3mat88jonmatxxx2.19d99e0d54a6e18d00c105200e7175308bf6aa17e 它在 80% 的时间内都可以正常工作,这并不奇怪,在测试情况下,这种问题通常会在 100% 的时间内正常工作! ???s 可能是先前消息的一部分。第一步,处理你的信息框架。编写一些测试,在缓冲区中使用各种部分消息调用您的代码,您只需要调用ProcessReceieve() 的代码并将其传递给您已经填充了一些数据的SocketAsyncEventArgs。从一条完整的消息开始,然后为分成两部分到达的消息编写测试,然后是包含两条消息的缓冲区,等等。确保拆分 unicode 字符。 或者使用类似这样的工具:codeproject.com/KB/IP/testingsocketservers.aspx 强制您的服务器处理部分读取消息...【参考方案2】:

我看到的问题是您在当前从套接字读取时收到的缓冲区上调用 Encoding.Unicode.GetString()。但是,该缓冲区的内容可能不是字符串的有效 unicode 编码。

您需要做的是缓冲整个流,然后在收到所有数据后,在最后一次操作中将其解码为字符串。

【讨论】:

以上是关于SocketAsyncEventArgs 和缓冲,而消息是在部分的主要内容,如果未能解决你的问题,请参考以下文章

TCP Socket SendAsync操作是否可以在不传输BufferList中的所有字节的情况下完成?

C# SocketAsyncEventArgs 和网络故障

SocketAsyncEventArgs.Completed 在 Windows 8 中不会触发

是否有必要清理 SocketAsyncEventArgs.Completed?

c# SocketAsyncEventArgs 在 ReceiveAsync 处理程序中阻塞代码

C#高性能大容量SOCKET并发:SocketAsyncEventArgs封装