socket的阻塞与非阻塞
同步:主动请求并等待IO操作完成的方式
异步:主动请求数据后,可以去处理其它任务,随后等待IO操作完毕的通知
阻塞:线程持续等待资源中数据准备完成,直到返回响应结果
非阻塞:线程直接返回结果,不会持续等待资源准备数据结束后才响应结果
socket()函数创建的socket默认是阻塞的
可以在创建socket时设置为非阻塞:(type参数中设置SOCK_NONBLOCK标志)
int sockfd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, IPPROTO_TCP);
也可以使用fcntl修改文件状态:
flags = fcntl( s, F_GETFL, 0 ) // 得到文件状态标志
fcntl( s, F_SETFL, flags | O_NONBLOCK ) // 设置为非阻塞
不同的程序在进行网络通信时,发送的一方会将内核缓冲区的数据通过网络传输给接收方的内核缓冲区。
在应用程序A与应用程序B建立连接之后,假设应用程序A不断调用send函数,则数据会不断拷贝至对应的内核缓冲区中,如果应用程序B一直不调用recv函数,那么在应用程序B的内核缓冲区被填满之后,应用程序A的内核缓冲区也会被填满,此时应用程序A继续调用send函数会发生什么结果?
当socket是阻塞模式时,继续调用send/recv函数,程序会阻塞在send/recv调用处;
当socket是非阻塞模式时,继续调用send/recv函数,send/recv不会阻塞程序执行流,而是立即出错返回,我们会得到一个相关的错误码,在Linux上该错误码为EWOULDBLOCK或EAGAIN。