什么阻塞意味着setsockopt参数SO_RCVTIMEO

时间:2013-01-10 01:43:37

标签: c++ setsockopt

当我从msdn link查看setsockopt时。我遇到了一个参数SO_RCVTIMEO,它的描述是“设置阻塞接收调用的超时时间,以毫秒为单位。”我认为套接字监听操作是事件驱动的,这意味着当内核从NIC卡中排出帧时通知我的程序套接字,那么什么阻塞呢?

2 个答案:

答案 0 :(得分:3)

recv和WSARecv函数正在阻塞。它们不是事件驱动的(至少不是在调用级别)。即使阻塞有超时(使用SO_RECTIMEO选项设置),就代码而言,它们不是事件驱动的。在这种情况下,它们只是伪阻塞(可以说是非阻塞,取决于超时有多短)。

当您调用WSARecv时,它将等待数据准备好被读取。虽然数据尚未准备好被读取,但它只是等待。这就是它被认为是封锁的原因。


你是正确的,因为它的核心网络是事件驱动的。在引擎盖下,计算机本质上是事件驱动的。这是硬件的工作方式。硬件中断本质上是事件。你是对的,在低级别发生的事情是你的NIC卡告诉操作系统它已经准备好被读取了。在那个级别,它确实是基于事件的。

问题是WSARecv等待那个事件。


这是一个有希望的明确类比。想象一下,由于某种原因你不能离开你的房子。现在想象你的朋友F住在隔壁。另外,假设你的另一个朋友G在你家。

现在想象一下,你给G一张纸上写了一个问题并请他把它带到F。

一旦发出问题,想象你发送G去获得F的回复。这就像recv电话。 G会等到F写下他的回复,然后他会把它带给你。如果F尚未写入,G不会立即转身并返回。

这是差距的来源。 G确实知道“F写的!”事件,但你不是。你不是直接看那张纸。

设置超时意味着你告诉G在放弃和回来之前最多等待一段时间。在这种情况下,G仍在等待F写入,但如果F在x毫秒内没有写入,则G转身并空手回来。

基本上,recv的伪代码含糊不清:

1) is data available?
  1a) Yes: read it and return
  1b) No: GOTO 2
2) Wait until an event is received
  2a) GOTO 1

我知道这是一个非常令人费解的解释,但我的主要观点是:recv正在与事件交互,而不是代码。 recv阻塞,直到收到其中一个事件。如果设置了超时,它将一直阻塞,直到收到其中一个事件,达到超时。

答案 1 :(得分:2)

默认情况下,套接字不是事件驱动的。您必须编写额外的代码才能启用它。最初以阻塞模式创建套接字。这意味着默认情况下,对send()recv()accept()的调用将无限制地阻塞调用线程,直到请求的操作完成为止。

对于recv(),这意味着调用线程被阻塞,直到至少有1个字节可用于从套接字的接收缓冲区读取,或者直到发生套接字错误(以先发生者为准)。 SO_RCVTIMEO允许您在阻止读取上设置超时,以便recv()退出时出现WSAETIMEDOUT错误,如果在超时之前没有可用的数据可用。

实现超时的另一种方法是通过ioctlsocket(FIONBIO)将套接字设置为非阻塞模式,然后在超时时调用select(),然后调用recv()或{{1仅当accept()报告套接字处于可读状态时,select()仅当send()报告套接字处于可写状态时。但这需要更多代码来管理套接字进入阻塞状态的情况,导致操作失败并出现select()错误。