Linux UDP 套接字:为什么 select()?
Linux UDP Socket: why select()?
我是 Linux 套接字编程的新手。这里我有一个基本问题:
为了 UDP
,为什么我们需要 select()
?
由于 UDP
是无状态的,所以 UDP 服务器只处理它收到的任何数据。新的client发送数据后不会创建新的socket吧?
如果是这样,一旦此套接字有数据到达,select()
将是 returned/notified。所以我们不需要全部通过吞吐量来检查哪个套接字被通知(因为只有一个套接字);
这是真的吗? non-blocking UDP socket
+ select()
== blocking UDP socket
.
谢谢!
select()
的主要好处是能够同时等待多个描述符的输入。因此,当您打开多个 UDP 套接字时,将它们全部放入 fd_set
,调用 select()
,当其中任何一个收到数据包时,它将 return。它 return 是一个 fd_set
,表示哪些有可用数据。您还可以使用它来等待来自网络的数据,同时也等待来自用户终端的输入。或者您可以在单个服务器中同时处理 UDP 和 TCP 连接(例如,可以使用 TCP 或 UDP 访问 DNS 服务器)。
如果不使用 select()
,则必须编写一个循环,在每个套接字上连续执行非阻塞读取。这效率不高,因为它会花费大量时间执行不必要的系统调用(想象一个服务器一天只收到一个请求,但整天都在不断调用 recv()
)。
您的问题似乎假设服务器只能使用一个 UDP 套接字。但是,如果服务器有多个 IP 地址,则可能需要多个套接字。 UDP 客户端通常希望响应来自他们向其发送请求的同一 IP。标准套接字 API 不提供知道请求发送到哪个 IP 或设置传出回复的源地址的方法。所以实现这个的常用方法是打开一个单独的套接字绑定到每个 IP,并使用 select()
或 epoll()
来同时等待对所有 IP 的请求。然后您通过接收请求的同一个套接字发送回复,它将使用该套接字的绑定 IP 作为源。
(Linux 有套接字扩展,不需要这样做,参见 Setting the source IP for a UDP socket。)
我是 Linux 套接字编程的新手。这里我有一个基本问题:
为了 UDP
,为什么我们需要 select()
?
由于
UDP
是无状态的,所以 UDP 服务器只处理它收到的任何数据。新的client发送数据后不会创建新的socket吧?如果是这样,一旦此套接字有数据到达,
select()
将是 returned/notified。所以我们不需要全部通过吞吐量来检查哪个套接字被通知(因为只有一个套接字);这是真的吗?
non-blocking UDP socket
+select()
==blocking UDP socket
.
谢谢!
select()
的主要好处是能够同时等待多个描述符的输入。因此,当您打开多个 UDP 套接字时,将它们全部放入 fd_set
,调用 select()
,当其中任何一个收到数据包时,它将 return。它 return 是一个 fd_set
,表示哪些有可用数据。您还可以使用它来等待来自网络的数据,同时也等待来自用户终端的输入。或者您可以在单个服务器中同时处理 UDP 和 TCP 连接(例如,可以使用 TCP 或 UDP 访问 DNS 服务器)。
如果不使用 select()
,则必须编写一个循环,在每个套接字上连续执行非阻塞读取。这效率不高,因为它会花费大量时间执行不必要的系统调用(想象一个服务器一天只收到一个请求,但整天都在不断调用 recv()
)。
您的问题似乎假设服务器只能使用一个 UDP 套接字。但是,如果服务器有多个 IP 地址,则可能需要多个套接字。 UDP 客户端通常希望响应来自他们向其发送请求的同一 IP。标准套接字 API 不提供知道请求发送到哪个 IP 或设置传出回复的源地址的方法。所以实现这个的常用方法是打开一个单独的套接字绑定到每个 IP,并使用 select()
或 epoll()
来同时等待对所有 IP 的请求。然后您通过接收请求的同一个套接字发送回复,它将使用该套接字的绑定 IP 作为源。
(Linux 有套接字扩展,不需要这样做,参见 Setting the source IP for a UDP socket。)