C# · 12月 19, 2021

C网络通信:阻塞与非阻塞socket的基本概念及简单实现

一、前言

最近在做Matalb/Simulink与C/C++的混合编程,主要是完成TCP、UDP、SerialPort等常见通信方式的中间件设计,为Simulink模型提供数据采集及解析模块。

问题在于没有搞清楚Simulink中调用C/C++的内在机制,将测试OK的C++程序移植到mex上时,总会出现很多问题,比如通信的阻塞与非阻塞,有时候自己写半天可能在性能上并不比Matalb内置模块好,所以搞清楚一些原理性的东西还是很有必要的。

参考资料:

1.阻塞与非阻塞socket的优缺点https://blog.csdn.net/taotaoah/article/details/52441517

2.创建TCP/IP客户端对象以通过TCP/IP进行通信https://ww2.mathworks.cn/help/matlab/ref/tcpclient.html

3.阻塞与非阻塞socket的优缺点http://www.cnblogs.com/sunada2005/p/3591378.html

4.tcp socket阻塞与非阻塞https://blog.csdn.net/xdshengk/article/details/51066959

5.从linux源码看socket的阻塞和非阻塞https://blog.csdn.net/u011418530/article/details/79875707

二、基本概念

简单转载一点上述文章中对阻塞与非阻塞的优缺点对比,其实应该是根据实际情况来选择,但没搞明白Matlab及Simulink中的TCPClient到底是阻塞还是非阻塞的实现。

所谓阻塞方式的意思是指,当试图对该文件描述符进行读写时,如果当时没有东西可读,或者暂时不可写,程序就进入等待状态,直到有东西可读或者可写为止。

而对于非阻塞状态,如果没有东西可读,或者不可写,读写函数马上返回,而不会等待(这也与设置的超时时间有关)。

非阻塞,就是进程或线程执行此函数时不必非要等待事件的发生,一旦执行肯定返回,以返回值的不同来反映函数的执行情况,如果事件发生则与阻塞方式相同,若事件没有发生则返回一个代码来告知事件未发生,而进程或线程继续执行,所以效率较高;

简单的讲,阻塞就是GET,非阻塞就是PUT;

阻塞好控制,不发送完数据程序不会走下去,但是对性能有影响。

非阻塞不太好控制,可能和能力有关,但是性能会得到很大提升。

阻塞式的编程方便,非阻塞的编程不方便,需要程序员处理各种返回;

阻塞处理简单,非阻塞处理复杂;

阻塞效率低,非阻塞效率高;

阻塞模式,常见的通信模型为多线程模型,服务端accept之后,对每个socket创建一个线程去recv。

逻辑上简单,适用于并发量小(客户端数目少),连续传输大数据量的情况下,比如文件服务器。

还有就是在客户端recv服务器消息的时候也经常用,因为客户端就一个socket,用阻塞模式不影响效率,而且编程逻辑上要简单得多。

非阻塞模式,常见的通信模型为select模型和IOCP模型,适用于高并发,数据量小的情况,比如聊天室;

客户端多的情况下,如果采用阻塞模式,需要开很多线程,影响效率;

另外,客户端一般不采用非阻塞模式。

未完待续….