C多进程实现聊天服务

一、概述

  案例:使用多进程实现聊天服务。要求:可以有多个客户端连接,且客户端发送什么数据服务端就回复什么数据

  实现步骤:

  1.创建监听文件描述符socket

  2.绑定端口bind

  3.监听端口listen

  4.当接受到一个连接时开启一个子进程来实现,来实现和客户端的通讯(fork)

  5.具体客户端通讯的方法read\write

二、代码示例

  

//多进程版网络服务器(优化版)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/wait.h>
#include <signal.h>
#include <ctype.h>
#include "wrap.h"

//信号处理函数
void waitchild(int signo){
        pid_t wpid;
        while(1){
                wpid = waitpid(-1,NULL,WNOHANG);
                if(wpid>0){
                        printf("child exit,wpid=[%d]\n",wpid);
                }else if(wpid==0||wpid==-1){
                        break;
                }
        }
int main(){
        //创建Socket
        int lfd = Socket(AF_INET,SOCK_STREAM,0);
        //设置端口复用
        int opt;
        setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(int));
        //绑定
        struct sockaddr_in serv;
        serv.sin_family = AF_INET;
        serv.sin_port = htons(8888);
        serv.sin_addr.s_addr = htonl(INADDR_ANY);
        Bind(lfd,(struct sockaddr *)&serv,sizeof(serv));

        //监听
        Listen(lfd,128);

        //阻塞信号
        sigset_t mask;
        sigemptyset(&mask);
        sigaddset(&mask,SIGCHLD);
        sigprocmask(SIG_BLOCK,&mask,NULL);

        int cfd;
        socklen_t len;
        char sIP[16];
        pid_t pid;
        struct sockaddr_in client;
        while(1){
                //等待客户端连接
                memset(sIP,0x00,sizeof(sIP));
                len = sizeof(client);
                bzero(&client,sizeof(client));

                cfd = Accept(lfd,(struct sockaddr *)&client,&len);

                //创建子进程
                pid = fork();
                if(pid<0){//创建进程失败
                        perror("fork error");
                        close(lfd);
                        return -1;
                }else if(pid>0){//如果是父进程
                                //关闭通讯描述符
                        close(cfd);
                        //注册SIGCHLD信号处理函数
                        struct sigaction act;
                        act.sa_handler = waitchild;
                        act.sa_flags = 0;
                        sigemptyset(&act.sa_mask);
                        //解除对SIGCHLD信号的阻塞
                        sigprocmask(SIG_UNBLOCK,&mask,NULL);
                }else if(pid==0){//如果是子进程
                        //关闭监听文件描述符
                        close(lfd);
                        int i =0;
                        int n=0;
                        char buf[1024];
                        while(1){
                                memset(buf,0x00,sizeof(buf));
                                n = Read(cfd,buf,sizeof(buf));
                                if(n<=0){
                                        printf("read error or client closed,n==[%d]\n",n);
                                        break;
                                }
                                printf("read over,n==[%d],buf=[%s]\n",n,buf);
                                for(i=0;i<n;i++){
                                        buf[i] = toupper(buf[i]);
                                }
                                write(cfd,buf,n);
                        }
                        close(cfd);
                        exit(0);
                }


        }
        //关闭监听文件描述符
        close(lfd);
        return 0;
}
   

  

posted on 2021-12-13 13:39  飘杨......  阅读(71)  评论(0编辑  收藏  举报