多进程并发C/S通信基本模型及实现

来源:互联网 发布:调节阀选型计算软件 编辑:程序博客网 时间:2024/06/03 23:47

本例实现如下功能:
服务端接收来自客户端发送过来的字符串,将小写转换为大写后发送回客户端。
其中,每一个新客户端连接后,服务端主进程为此客户端创建一个子进程进行数据的处理。


多进程并发服务端代码

/*server.c*/#include <stdio.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <signal.h>#include <sys/wait.h>#include <sys/types.h>#include <stdlib.h>#include <errno.h>#include <sys/socket.h>#define BUFSIZE 666#define SERV_PORT 8888int main(){    struct sockaddr_in servaddr, cliaddr;    socklen_t cliaddr_len;    int listenfd, connfd;    char buf[BUFSIZE];    char str[INET_ADDRSTRLEN];    int i, n;    pid_t pid;    listenfd = socket(AF_INET, SOCK_STREAM, 0);  //打开一个网络通讯端口,分配一个文件描述符listenfd    bzero(&servaddr, sizeof(servaddr));          //清空服务端套接字    servaddr.sin_family = AF_INET;               //地址采用IPv4地址     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//地址从主机字节顺序转换成网络字节顺序    servaddr.sin_port = htons(SERV_PORT);        //端口号从主机字节顺序转换成网络字节顺序    /*将文件描述符listenfd和服务器地址绑定在一起*/    bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr));    /*声明listenfd处于监听状态,链接个数限制为5*/    listen(listenfd, 20);    printf("等待连接....\n");    while(1){        cliaddr_len = sizeof(cliaddr);        /*connfd文件描述符用于和客户端通信,服务端调用accept()接受连接*/        connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &cliaddr_len);        pid = fork();        if(pid == 0){  //创建一个子进程处理数据            close(listenfd);//关闭子进程端的监听                    while(1){                /*从connfd文件描述符指向的文件读取数据*/                n  = read(connfd, buf, BUFSIZE);                if(n == 0){                    printf("另一端已关闭\n");                    break;                }                /*服务端打印*/                printf("从地址%s 端口号%d 接收到数据\n",                         (char*)inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),                        ntohs(cliaddr.sin_port));                /*将buf转化为大写后写入connfd*/                        for(i = 0; i < n;i++ ){                    buf[i] = toupper(buf[i]);                }                    write(connfd, buf, n);            }                close(connfd);//处理完毕关闭连接            exit(0);        }else if(pid > 0){ //父进程            close(connfd);//任务交由子进程处理,父进程关闭        }else{            printf("fork err\n");        }        if(n == 0 ||  n == -1){            break;        }    }    return 0;}

多进程并发客户端代码

/*client.c*/#include <stdio.h>#include <string.h>#include <unistd.h>#include <netinet/in.h>#define BUFSIZE 666#define SERV_PORT 8888int main(int argc, char *argv[]){    struct sockaddr_in servaddr;    char buf[BUFSIZE];    int sockfd, n;    sockfd = socket(AF_INET, SOCK_STREAM, 0);    bzero(&servaddr, sizeof(servaddr));    servaddr.sin_family = AF_INET;    inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);    servaddr.sin_port = htons(SERV_PORT);    /*连接服务器*/    connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr));    while(fgets(buf, BUFSIZE, stdin) != NULL){        write(sockfd, buf, strlen(buf));        /*接收服务端数据*/        n = read(sockfd, buf, BUFSIZE);        if(n == 0){            printf("server closed\n");        }else{            /*打印输出buf*/            write(STDOUT_FILENO, buf, n);        }    }    close(sockfd);    return 0;}

执行测试

yu@ubuntu:~/Linux/219/duojincheng$ lsclient.c  server.cyu@ubuntu:~/Linux/219/duojincheng$ gcc -o server server.cyu@ubuntu:~/Linux/219/duojincheng$ gcc -o client client.cyu@ubuntu:~/Linux/219/duojincheng$ ./server等待连接....从地址127.0.0.1 端口号32874 接收到数据从地址127.0.0.1 端口号32874 接收到数据从地址127.0.0.1 端口号32875 接收到数据从地址127.0.0.1 端口号32874 接收到数据从地址127.0.0.1 端口号32875 接收到数据

另开一终端执行客户端:

yu@ubuntu:~/Linux/219/duojincheng$ ./clienthey guysHEY GUYSguole byeGUOLE BYE

另开一终端执行客户端:

yu@ubuntu:~/Linux/219/duojincheng$ ./clientnihao ma  wo hen hao neNIHAO MA  WO HEN HAO NEzai jianZAI JIANssssssssssssssSSSSSSSSSSSSSS

这里写图片描述

0 0
原创粉丝点击