学习笔记(03):C++网络编程进阶-socket的阻塞与非阻塞

立即学习:https://edu.csdn.net/course/play/6082/113752?utm_source=blogtoedu

阻塞和非阻塞

Windows套接字在阻塞和非阻塞两种模式下执行I/0操作,在阻塞模式下,在IO操作完成之前,执行的操作函数一直等待而不会立即执行,该函数所在的线程会阻塞在这里,相反,在非阻塞模式下,套接字函数会立即返回,而不管IO是否完成,该函数所在的线程会继续运行。

 

‘阻塞模式的套接字上,调用任何一个Windows Sockets API都会耗费等待时间。

比如当调用recv函数时,系统首先查是否有准备好的数据,如果数据没有准备好,那么系统就会处于等待状态,当数据准备好后,将数据从系统内核缓冲区复制到用户空间,然后该函数返回,在套接应用程序中,当调用recv函数时,未必用户空间就已经存在数据,那么此时recv函数就会处于等待状态。

四种阻塞API调用

输入操作:

recv(),recvfrom()函数,以阻塞套接字为参数调用该函数接收数据,如果此时套接字缓冲区内没有数据可读,则调用线程在数据到来之前一直睡眠。

输出操作:

send(),sendto()函数,以阻塞套接字为参数调用该函数发送数据,如果套接字缓冲区没有可用空间,线程会一直睡眠,直到有空间。

接收连接:

accept()函数,以阻塞套接字为参数调用该函数,等待接收连接请求,如果此时没有连接请求,线程就会进入睡眠状态。

外出连接:

connect()。对于TCP连接,客户端以阻塞套接字为参数,调用该函数想服务器发起连接,该函数在收到服务器的应答前,不会返回,这意味着TCP连接总会等待至少到服务器的一次往返时间。

注:并不是所有的Windows Socket API以阻塞套接字为参数调用都会发生阻塞,例如以阻塞模式的套接字为参数调用bind(),listen()函数时,函数会立即返回。

 

当使用socket()函数和WSASocket函数创建套接字时,默认都是阻塞的,在创建套接字之后,windows下通过调用ioctlsocket()函数将该套接字设置为非阻塞模式。

套接字设置为非阻塞模式后,在调用windwos Sockets API函数时,调用函数会立即返回,大多数情况下,这些函数调用都会调用“失败”,并返回WSAEWOULDBLOCK错误代码,说明请求的操作在调用期间没有时间完成,通常,应用程序需要重复调用该函数,直到获得成功的返回代码,但特例bind()函数不会返回该错误。

除了使用ioctlsocket()函数将套接字,设置为非阻塞模式之外,还可以使用WSASsyncselect()和WSAEventselect()函数,当调用该函数时,套接字会自动的设置为非阻塞方式。

由于使用非阻塞套接字在调用函数时,会经常返回WSAEWOULDLOCK错误,所以在任何时候都应仔细检查返回代码并做好“失败”准备,应程序连续不断的调用这个函数,知道他返回成功只是为止,上面额程序清单中,字while循环体内不断调用recv函数,以读入1024个字节的数据,这种做法很浪费系统资源。

模式

优点

缺点

阻塞套接字blocking

阻塞模式的套接字,开发网络程序比较简单,容易实现,当希望能够立即发送和接收数据,且处理的套接字数量比较少的情况下,使用阻塞模式来开发网络程序比较合适

缺点是当希望同时处理大量套接字时,将无从下手,其扩展性很差,大量为每个套接字都分别分配一个度线程,一个处理数据线程和一个用于同步的事件,那么这样无疑加大系统的开销

非阻塞套接字not_blocking

非阻塞套接字在控制建立的多连接,在数据的收发量不均,时间不定时,明显具有优势,这种套接字在使用上存在一定难度,但只要排除了这些困难,它在功能上还是非常强大的,通常情况下,可考虑使用套接字IO模型,它有助于应用程序通过异步方式,同事对一个或多个套接字的通信加以管理。

编写复杂,不容易使用

你可能感兴趣的:(研发管理)