Unix系统编程(4) - 多进程并发服务器

来源:互联网 发布:什么叫网络电视 编辑:程序博客网 时间:2024/06/02 03:26

1. 迭代服务器 & 并发服务器

服务器按照 处理方式 来看可以分为:

1.1 迭代服务器

迭代服务器只能一次处理一个客户的请求。也就是说在服务器响应一个客户请求时,如果有另一个客户发起请求是不能得到及时响应的。下图是一个典型的迭代服务器处理流程。


迭代服务器

1.2 并发服务器

并发服务器则能同时处理多个客户端请求。下图是一个基于多进程模型的并发服务器处理流程。


多进程并发服务器

2. 多进程并发服务器

1. 客户端调用connet发起连接


客户端调用connet发起连接

2. 服务器accept阻塞返回,建立连接成功


accept

3. 服务器端调用fork()创建子进程


这里写图片描述

4. 服务器端关闭连接套接字,子进程关闭监听套接字



5. 子进程中处理客户请求,父进程继续处于accept()阻塞监听状态。

3. 简单实现

源码可以到: Github连接上进行下载。

服务器端源码:

#include <stdio.h>#include <sys/types.h>          /* See NOTES */#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <arpa/inet.h>#define SERV_PORT 8000#define MAXLINE 1024int main(){    int fd, confd, clientaddrlen, revlen, i;    struct sockaddr_in serveraddr, clientaddr;    char str[INET_ADDRSTRLEN];    char buf[MAXLINE];    pid_t pid;    //1. 创建一个socket    fd = socket(AF_INET, SOCK_STREAM, 0);    //2. 绑定一个端口    bzero(&serveraddr, sizeof(serveraddr));    serveraddr.sin_family = AF_INET;    serveraddr.sin_port = htons(SERV_PORT);    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);    bind(fd, (struct sockaddr*)&serveraddr, sizeof(serveraddr));    //3. 设置监听    listen(fd, 20);    printf("Accepting Connecting...\n");    while(1)    {        //4.接受链接        clientaddrlen = sizeof(clientaddr);        confd = accept(fd, (struct sockaddr*)&clientaddr, &clientaddrlen);        pid = fork();        if(pid == 0)        {            close(fd);            while(1)            {                revlen = read(confd, buf, MAXLINE);                if(revlen == 0)                {                    printf("closed\n");                    break;                }                printf("client: %s\t port: %d\n",                inet_ntop(AF_INET, &clientaddr.sin_addr, str, sizeof(str)),                ntohs(clientaddr.sin_port));                i = 0;                while(i < revlen)                {                    buf[i] = toupper(buf[i]);                    ++i;                }                write(confd, buf, revlen);            }            close(confd);            return 0;        }        else if(pid > 0)        {            close(confd);        }        else        {            printf("fork err\n");        }    }    close(fd);    return 0;}

测试用客户端源码:

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#define MAXLINE 80#define SERV_PORT 8000int main(int argc, char *argv[]){    //sockaddr_in IPv4    struct sockaddr_in servaddr;    char buf[MAXLINE];    int sockfd, n;    //1. 创建一个套接字    sockfd = socket(AF_INET, SOCK_STREAM, 0);    //2. 链接到本机8000端口服务器    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, MAXLINE, stdin) != NULL)    {        //3. 向服务器发送数据        write(sockfd, buf, strlen(buf));        //4. 读取服务器的回传数据        n = read(sockfd, buf, MAXLINE);        printf("Response from server:\n");        write(STDOUT_FILENO, buf, n);    }    //5. 关闭套接字描述符    close(sockfd);    return 0;}
1 0
原创粉丝点击