简体   繁体   English

消息部分时,SocketAsyncEventArgs和缓冲

[英]SocketAsyncEventArgs and buffering while messages are in parts

C# socket server, which has roughly 200 - 500 active connections, each one constantly sending messages to our server. C#套接字服务器,大约有200-500个活动连接,每个连接不断向我们的服务器发送消息。

About 70% of the time the messages are handled fine (in the correct order etc), however in the other 30% of cases we have jumbled up messages and things get screwed up. 大约有70%的时间对消息进行了正确处理(以正确的顺序等),但是在另外30%的情况下,我们将消息弄乱了,事情变糟了。 We should note that some clients send data in unicode and others in ASCII, so that's handled as well. 我们应该注意,一些客户端以unicode发送数据,而另一些以ASCII发送数据,因此也可以处理。

Messages sent to the server are a variable length string which end in a char3, it's the char3 that we break on, other than that we keep receiving data. 发送到服务器的消息是一个可变长度的字符串,其结尾为char3,这是我们中断的char3,而不是我们继续接收数据。

Could anyone shed any light on our ProcessReceive code and see what could possibly be causing us issues and how we can solve this small issue (here's hoping it's a small issue!) 任何人都可以对我们的ProcessReceive代码有所了解,看看可能导致我们出现问题的原因以及我们如何解决这个小问题(希望这是个小问题!)

Code below: 代码如下:

Firstly, I'm sure you know, but it's always worth repeating; 首先,我确定你知道,但这总是值得重复的; TCP is a stream of bytes. TCP是字节流。 It knows nothing of any application level "messages" that you may determine exist in that stream of bytes. 它不知道您可以确定该字节流中是否存在任何应用程序级别的“消息”。 All successful socket Recv calls, whether sync or async, can return any number of bytes between 1 and the size of the buffer supplied. 所有成功的套接字Recv调用,无论同步还是异步,都可以返回1到提供的缓冲区大小之间的任意数量的字节。

With that in mind you should really be dealing with your message framing (ie looking for your delimiter) before you do anything else. 考虑到这一点,在执行其他任何操作之前,您应该真正处理消息框架(即查找分隔符)。 If you don't find a delimiter then simply reissue the read using the same SocketAsyncEventArgs , the same buffer and set the offset to where you currently are, this will read some more data into the buffer and you can take another look for the delimiter once the next read has completed... Ideally you'd keep track of where you last got to when searching for a delimiter in this buffer to reduce repeated scanning... 如果找不到分隔符,则只需使用相同的SocketAsyncEventArgs ,相同的缓冲区重新发出读取,并将偏移量设置为当前位置,这会将更多数据读入缓冲区,并且您可以再次查看分隔符下一次读取已完成...理想情况下,当在此缓冲区中搜索定界符以减少重复扫描时,您最好跟踪上一次到达的位置...

Right now you're not doing that and your use of e.Buffer[e.Offset] == 255 will fail if you get a message that arrives in pieces as you could be referring to any byte in the message if the message is split over multiple reads. 现在,您没有执行此操作,并且如果收到的消息是e.Buffer[e.Offset] == 255 ,则对e.Buffer[e.Offset] == 255将失败,因为如果e.Buffer[e.Offset] == 255了消息,则e.Buffer[e.Offset] == 255消息中的任何字节多次读取。

The problem I am seeing is that you are calling Encoding.Unicode.GetString() on a buffer you received in the current read from socket. 我看到的问题是您正在从套接字当前读取的缓冲区上调用Encoding.Unicode.GetString()。 However, the contents of that buffer might not be a valid unicode encoding of a string. 但是,该缓冲区的内容可能不是字符串的有效unicode编码。

What you need to do is to buffer your entire stream, and then decode it as a string in one final operation, after you have received all the data. 您需要做的是缓冲整个流,然后在收到所有数据后,在一个最终操作中将其解码为字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM