socket的阻塞与非阻塞

本文详细介绍了Windows套接字在阻塞模式与非阻塞模式下的工作原理及特点。阻塞模式下,套接字API调用会在I/O操作完成前一直等待;而非阻塞模式则立即返回,无论I/O操作是否完成。文章还对比了两种模式的优缺点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阻塞(blocking)、非阻塞(non-blocking):

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

1. 阻塞模式

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

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

image-20210411121958517

四种阻塞API调用

  • 输入操作

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

  • 输出操作

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

  • 接收函数

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

  • 外出连接

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

注意:

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

2. 非阻塞模式

image-20210411122758915

把套接字设置为非阻塞模式,即通知系统内核:在调用SocketsAPI时,应让函数立即返回,并返回一个错误代码。

比如,一个非阻塞模式套接字多次调用recv()函数的过程。前三次调用recv()函数时,内核数据还没有准备好。因此,该函数立即返回WSAEWOULDBLOCK错误代码。第四次调用recv()函数时,数据已经准备好,被复制到应用程序的缓冲区中,recv()函数返回成功指示,应用程序开始处理数据。

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

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

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

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

3. 优缺点对比

image-20210411123400718

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超级D洋葱

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值