多进程TCP并发服务器
最初的服务器都是迭代服务器,服务器处理完一个客户的请求,再接受下一个客户的请求。但是我们的期望应该是一台服务器同时为多个客户服务。实现并发服务器最简单的办法就是为每个客户均一个子进程。
基本思路
基本流程是,建立连接,返回后,服务器调用,子进程通过已连接套接口()为客户提供服务,父进程通过监听套接口()等待另一个连接。子进程开始处理客户后,父进程便关闭已连接套接口。
...listenfd=socket(AF_INET,SOCK_STREAM,);bind(listenfd,(SA*)&servaddr,sizeof(servaddr));listen(listenfd,LISTENQ);for(;;){connfd=accept(listenfd,(SA*)&cliaddr,&clilen));if((childpid=Fork())==){/* 子进程 */close(listenfd);/* 子进程关闭监听套接口 */doit(connfd);/* 子进程通过已连接套接口处理请求 */close(connfd);/* 子进程处理请求完毕,关闭已连接套接口 /* 这一步可省略,因为exit会关闭所有由内核打开的描述字 */exit();/* 子进程结束 */}close(connfd);/* 父进程关闭已连接套接口 */}
描述字访问计数
对TCP套接口调用会引发FIN,终止连接。但是上面父进程的却并没有影响子进程使用这个描述字进行客户请求处理,这是因为,父进程调用只是将它的文件表项访问计数减一,文件表项访问计数值为0时才真正关闭。
返回,计数=1
返回,计数=2
父进程,计数=1
子进程,计数=0,引发FIN,终止连接
分步骤状态图解
下图是服务器阻塞于调用、连接请求从客户到达时客户和服务器的状态。
accept返回前客户-服务器的状态
返回后,就有下图的状态。连接被内核接受,新的套接口即被创建,这个已连接套接口,可用来读写数据。
accept返回后客户-服务器的状态
并发服务器的下一步是调用,下图是从返回后的状态。此时描述字和是父进程-子进程共享的。
fork返回后客户-服务器的状态
下一步是父进程关闭已连接套接口,子进程关闭监听套接口。
父子进程关闭相应套接口后客户-服务器的状态
最后的结果是子进程处理与客户的连接,父进程可对监听套接口调用来处理下一个连接。
领取专属 10元无门槛券
私享最新 技术干货