大家都知道socket在接收报文时有两种方式,一种方式是receive成为同步方式(这种方式的特点是自带阻塞,至于阻塞的时长和机制还没有弄清楚),还有一种是BeginReceive成为异步(这种方式的阻塞是可以根据我们的需要手动控制的),同步方式大家用得非常多,一般用于 对报文传输在时间上没有严格要求的地方,最终只要保证所传送的报文都能够被接收到,不管是分几次收到还是一次收入缓存,但同步方式在不给报文加入边界标示 时是很容易出现socket粘包现象的,而且在同步方式的基础上解决粘包的方法都很不理想。在这种情形下我们可以考虑使用异步方式。
今天这里我要说是异步方式,一般在对TCP传输过程中的分包有严格的要求时,我们都采用socket的异步方式,当然,异步方式相对同步方式在使用上略微复杂写,这也是大多人不是在万不得已的情况下不想使用它的愿意之一吧。
相 对同步方式,异步方式会有一个回调函数的调用,当缓冲区接收到一个包后回调函数被调用(处于缓冲区数据的代码一般都放置在回调函数中),回调函数被调用的 时候BeginReceive被阻塞,直到回调函数被执行完毕。(不过我在想,异步方式缓冲区收到一个包之前应该是按照IP包的包头和包尾标志进行了处 理,而同步方式则略过了这个步骤,只要两个包之间的间隔‘不太长’就把报文按照排队的方式送入了缓冲区,导致发生粘包的问题,这个不太长究竟是多长我还没 有弄清楚,也希望有高人能够指点)
在微软的文档中是这样描述的:
“Your callback method should implement the EndReceive method. When your application calls BeginReceive, the system will use a separate thread to execute the specified callback method, and will block on EndReceive until the Socket reads data or throws an exception.”
也就是说我们调用BeginReceive的时候,系统会幕后开启一个独立的线程,用以执行回调函数及对EndReceive的阻塞(block),直到EndReceive从socket的缓冲区中读到数据或者socket引发异常。
换 句话说如果我们在回调函数还没有被执行之前调用EndReceive则程序就被阻塞于此,直到获得数据为止或引发异常。所以一般我们还是要通过回调函数来 调用EndReceive方法(我的理解,如果EndReceive没有解除阻塞,则BeginReceive的缓冲区参数即socket的缓冲区无法继 续获取新的报文,或者说EndReceive的执行会导致缓冲区被清空)。