因为不知道客户端连接什么时候来,不知道客户端数据什么时候来,因此写死的服务端可能阻塞在accept,或者recv,因此必须用多进程,或者多线程处理已经连接客户端的通信。
对于多进程,当父进程获取到新的socket后,创建子进程,让子进程负责与该客户端进行通信,因为子进程会复制父进程的套接字文件描述符,而父进程只负责接收新的客户端的连接与其对应的新的文件描述符,此外它还要关闭这个获取的文件描述符,因为父进程不用这个文件描述符,不关掉会占用资源,还有就是父进程要重定义SIGCHLD信号的处理方式,因为当与某个客户端通信的子进程要结束时,会利用该信号通知父进程,而父进程此时要进行wait它,同意os对其资源进行回收。
对于多线程,当主线程获取到新客户端的socket时,要将其套接字文件描述符传到创建的子线程的入口函数中,让其进行与该客户端进行通信,但是主线程不能关闭该套接字文件描述符,因为线程之间共享文件描述符,主线程关闭导致子线程无法使用,此外创建线程后,之间将其分离,就不用线程等待了。
以下是多进程版的服务端、多线程版的服务端:
//服务端
2
3 #include "tcp.hpp"
4 using namespace std;
5
6 void sigcb(int num)//自定义信号处理方式
7 {
8 while(waitpid(-1, NULL, WNOHANG)>0);
9 }
10
11 int main(int argc, char* argv[])
12 {
13 //检查参数合法性