[学习笔记] Windows和Linux下Socket编程中select的应用

English Version:  https://today2tmr.com/en/2017/06/30/study-note-select-in-socket-for-windows-and-linux/

基本概念

I/O模型

系统处理I/O的模型,I/O即send和recv

同步/异步(针对客户端)

  • 同步: 一件一件事做。 在功能调用(向服务端提交请求)未得到结果前,调用不返回。
  • 异步: 调用功能后客户端即可做其他事情,得到结果时收到通知。
  • 区别:  客户端访问数据时进程是否阻塞

阻塞/非阻塞(针对服务端)

  • 阻塞: 调用结果返回之前,线程进入休眠状态。(如recv函数)
  • 非阻塞: 不能立即得到结果的情况下,立即返回。当有结果时用select通知客户端回调。
  • 区别:  服务端是否立即返回

Windows下的I/O模型

  • 阻塞模型
  • 选择模型
  • WSAAsyncSelect模型
  • WSAEventSelect模型
  • 重叠模型
  • 完成端口模型

阻塞模型即默认状态下的socket,使用简单,但是需要处理多个套接字时需要创建多个线程,即一个连接使用一个线程。

本文将主要总结选择模型。

这一网站中分别展示了用多线程和select实现的服务器。

Linux下的I/O模型

  • 阻塞I/O
  • 非阻塞I/O
  • I/O复用
  • 信号驱动的I/O
  • 异步I/O

select函数

Windows下的select

函数原型

参数及返回值说明

  • nfds: 0,无意义
  • readfds: 指向fd_set结构的可选指针,其中socket将会被检查可读性
  • writefds: 指向fd_set结构的可选指针,其中socket将会被检查可写性
  • exceptfds: 指向fd_set结构的可选指针,其中socket将会被检查是否发生错误
  • timeout: socket等待的最长时间,NULL即为阻塞操作
  • 返回: fd_set中可用的套接字个数,超时即为0

note: select函数会删除fd_set中无正在接受或正在发送数据的套接字

  • FD_CLR(s, *set)
    • 从set中移除套接字s
  • FD_ISSET(s, *set)
    • 若套接字s在set中返回非零值,否则返回0
  • FD_SET(s, *set)
    • 添加套接字s到set中
  • FD_ZERO(*set)
    • 初始化set为空s

使用步骤

  1. 用FD_ZERO宏来初始化我们感兴趣的fd_set。也就是select函数的第二三四个参数。
  2. 用FD_SET宏来将套接字句柄分配给相应的fd_set。如果想要检查一个套接字是否有数据需要接收,可以用FD_SET宏把套接接字句柄加入可读性检查队列中
  3. 调用select函数。如果该套接字没有数据需要接收,select函数会把该套接字从可读性检查队列中删除掉,
  4. 用FD_ISSET对套接字句柄进行检查。

Linux下的select

函数原型

参数及返回值说明

  • maxfd: 最大的描述符编号值加1
  • 其他: 与Windows下相同

  • FD_ZERO(int fd, fd_set* fds)
  • FD_SET(int fd, fd_set* fds)
  • FD_ISSET(int fd, fd_set* fds)
  • FD_CLR(int fd, fd_set* fds)

与Windows下相同

实例

学习资料

More:

One Reply to “[学习笔记] Windows和Linux下Socket编程中select的应用”

Leave a Reply

Your email address will not be published.