本篇是第三篇,主要用来讲解作为服务器的机器是如何管理多个socket的客户端连接的,毕竟recv只能监视单个socket。
一、背景介绍
在此之前,我们先来看下"操作系统是如何区分网络收到的数据是属于那一个socket的?"
答案:socket与端口号是一一对应的,操作系统会维护端口号到socket的索引结构,以快速读取,所以操作系统可以很方便的找到收到的网络数据属于那一个socket。
基于前面第2篇的知识,如果我们能够做到传递一个socket的列表,并且能够做到在socket列表没有数据的时候挂起进程,只要有一个socket有数据就唤醒这个进程貌似就可以解决这个问题。而这个也恰恰就是select的实现思路。
二、select介绍
我们通过使用select的代码来分析select的过程
int s = socket(AF_INET, SOCK_STREAM, 0);
bind(s, ...)
listen(s, ...)
int fds[] = // 用于存放需要监听的socket
while(1){ // 死循环,利用操作系统的进程阻塞和唤醒来工作
int n = select(..., fds, ...) // 传入fds
for(int i=0; i < fds.count; i++){ // 唤醒进程之后,遍历所有的socket
if(FD_ISSET(fds[i], ...)){ // 利用FD_ISSET来判断对应的socket是否有数据
// fds[i]的数据处理
}