一、select模型的特点
select
函数通常用于多路复用(multiplexing)操作,允许你同时监视多个套接字(sockets)的状态,并在其中任何一个套接字准备好进行 I/O 操作时进行响应。
以下是 select
模型的特点和作用:
-
并发处理多个套接字:
select
允许你同时监视多个套接字的状态,例如可读、可写、出错等,而不需要为每个套接字创建一个独立的线程。这使得在一个单独的线程中能够有效地管理多个连接。 -
事件驱动:
select
是事件驱动的,它会阻塞等待套接字上的事件发生,例如数据可读或可写。一旦有事件发生,它会通知你,你可以采取适当的操作响应这些事件。 -
跨平台: 尽管
select
最初是在 Unix 系统中引入的,但它也在 Windows 中提供支持。
实现原理:
- 每个客户端都有socket,服务器也有自己的socket,将所有的socket装进一个数组结构中,即数组,通过select函数遍历数组中的socket数组,当某个socket有响应时,select就会通过其参数/返回值反馈出来
- 如果检测到的是服务器socket,那么就是有客户端链接。
- 如果检测到的是客户端socket,那么就是客户端请求通信。
二、select函数
函数原型:
int select( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout );
参数介绍:
-
nfds
:表示最大套接字描述符(socket descriptor)加1的值。在 Windows 中,这个参数通常设置为要监视的最大套接字描述符的值加1。 -
readfds
:一个指向fd_set
结构体的指针,用于指定要监视可读事件的套接字集合。你可以使用FD_ZERO
和FD_SET
宏来设置和清除套接字集合中的套接字。 -
writefds
:一个指向fd_set
结构体的指针,用于指定要监视可写事件的套接字集合。 -
exceptfds
:一个指向fd_set
结构体的指针,用于指定要监视异常事件的套接字集合。 -
timeout
:一个指向struct timeval
结构体的指针,用于设置超时时间,以毫秒为单位。如果设置为NULL
,select
将会一直阻塞,直到有套接字就绪或出现错误。如果设置为0
,select
将立即返回,用于轮询套接字状态。
返回值:
- 如果
select
函数成功,它将返回可读、可写或异常事件的套接字数量,即就绪的套接字数量。 - 如果发生错误,
select
返回SOCKET_ERROR
,你可以使用WSAGetLastError
函数获取详细的错误码。