c语言多进程并发服务器

服务端

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
#include<strings.h>
#include<ctype.h>
#include<stdlib.h>
#include<signal.h>
#include<wait.h>
void do_sig(int num){
    while(waitpid(0,NULL,WNOHANG)>0);
}
int main(void){
    	//lfd:socket返回的文件描述符,用lfd监听并接受客户端连接
   		//cfd:客户端链接上来返回的cfd,用cfd和客户端通信
        int lfd,cfd,len,i;
        char buf[1024];//缓冲区
        //serv_addr服务器地址
        //client_addr客户端地址
        struct sockaddr_in serv_addr,client_addr;
        socklen_t client_len;
        //进程id
        pid_t pid;
        //杀死僵尸进程 
    	struct sigaction act;
    	act.sa_handler = do_sig;
   	 	act.sa_flags = 0;
    	sigemptyset(&act.sa_mask);
    	sigaction(SIGCHLD,&act,NULL);

    	//socket创建服务器返回lfd文件描述符
        lfd = socket(AF_INET,SOCK_STREAM,0);
        bzero(&serv_addr,sizeof(serv_addr));
        //ipv4
        serv_addr.sin_family = AF_INET;
        //端口 本地字节序转网络字节序 host to net short 大小端存储问题
        serv_addr.sin_port = htons(9999);
        //ip host to net long
        serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
        //bind
        bind(lfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
        //监听是否有客户连接
        listen(lfd,128);
        printf("wait for connect...\n");
        while(1){
           client_len = sizeof(client_addr);//客户端地址长度
           //连接成功返回cfd,用cfd和客户通信
           cfd = accept(lfd,(struct sockaddr*)&client_addr,&client_len);
           printf("connect success...\n");
           //创建进程
           pid = fork();
           if(pid==0){//child
                close(lfd);//子进程用不到lfd,因为lfd是父进程用来接收客户端连接的
                while(1){

			len = read(cfd,buf,sizeof(buf));
			printf("receive: %s\n",buf);
			if(len<=0)break;
			for(i=0;i<len;++i)
		    		 buf[i] = toupper(buf[i]);
			write(cfd,buf,len);
		}
		close(cfd);//客户端断开连接 
		return 0;
      }else if(pid>0) {//parent
	   	close(cfd);//父亲进程用不到cfd,因为cfd是子进程用来和客户端通信的 
      }else{
		perror("fork fail...");
		exit(1);
	    }
	}

}

客户端

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<sys/wait.h> 
#define DEST_PORT 9999//目标地址端口号 
#define DEST_IP "127.32.255.2"/*目标地址IP,这里设为本机,不一定非得是127.0.0.1,只要127开头并且不是127.0.0.0和127.255.255.255即可*/ 
#define MAX_DATA 100//接收到的数据最大程度 
 
int main(){
	int sockfd;
	struct sockaddr_in dest_addr;
	char buf[MAX_DATA];
 
	sockfd=socket(AF_INET,SOCK_STREAM,0);
	
	dest_addr.sin_family=AF_INET;
 	dest_addr.sin_port=htons(DEST_PORT);
	dest_addr.sin_addr.s_addr=inet_addr(DEST_IP);
	bzero(&(dest_addr.sin_zero),8);
	connect(sockfd,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr));

	printf("connect success");
	while(1){
		char send_buf[512] = "";
		scanf("%s",&send_buf);
		write(sockfd,send_buf,sizeof(send_buf));
		
		read(sockfd,send_buf,sizeof(send_buf));
    	printf("client receive:%s\n",send_buf);
	}

	return 0;
} 

centos执行
gcc -o server.out server.c
gcc -o client.out client.c
得到执行文件server.out,client.out
用xshell 对一个虚拟机开两个item窗口,一个执行./server.out ,另一个执行./client.out
可以用ps -aux 查看进程状态,看看有没有僵尸进程,本例中已经处理过僵尸进程