引入目的:为了解决一个服务器可以处理多个客户端,或者既能进行接收客户端连接,也能跟客户端进行通信,我们可以使用多进程或多线程完成

1> 使用多进程完成:父进程主要用于接收客户端的连接请求,子进程可以用于收发数据

2> 使用多线程完成:主线程可以用于接收客户端的连接请求,分支线程可以用于收发数据

多进程实现并发服务器

//信号处理函数
void handler(int signo)
{
    if(signo == SIGCHLD)
    {
        while(waitpid(-1, NULL, WNOHANG)>0);    
    }
}
 
sfd = socket();            //创建用于连接的套接字
bind();                //绑定端口号和IP地址
listen();               //将套接字设置为被动监听状态
 
signal(SIGCHLD, handler);
while(1)                    //循环接收客户端连接请求
{
 newfd = accept();        //接收客户端连接请求并创建出一个新的用于通信的套接字
 pid = fork();                 //创建子进程与客户端进行通信
    if(pid > 0)
    {
        close(newfd);    //新客户端套接字,对于父进程无用,直接关闭即可
    }else if(pid == 0)
    {
        //子进程用跟客户端进行通信工作
        close(sfd);      //父进程中的用于连接的套接字,对子进程无用,直接关闭
        send();
        recv();
        close(newfd);
        exit();    
    }
}
 
close(sfd);

多线程实现并发服务器

sfd = socket();         //创建用于连接的套接字 
bind();           //绑定
listen();         //将套接字设置成被动监听
 
while(1)           //主线程中循环接收客户端连接请求
{
    newfd = accept();       //每连接一个新的客户端,就会产生一个新的用于通信的套接字
    pthread_create(&tid, NULL, deal_cli_msg, &info);    //创建分支线程用于跟客户端通信
    pthread_detach(tid);                 //非阻塞,将线程设置成分离态,分支线程结束后,系统自动回收资源
}
close(sfd);         //关闭主线程中用于连接的套接字
 
//分支线程体,用于跟客户端通信使用
void *deal_cli_msg(void *arg)
{
    recv();
    send();
    close(newfd);
}