linux网络编程----->高并发--->多进程并发服务器

  在做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.

    常见的linux并发服务器模型;


    • 多进程并发服务器

    • 多线程并发服务器

    • select多路I/O转接服务器

    • poll多路I/O转接服务器

    • epool多路I/O转接服务器.



    本次主要讨论多进程并发服务器模型:

    linux网络编程----->高并发--->多进程并发服务器


    使用多进程并发服务器时要考虑以下几点:


    • 父进程最大文件描述个数(父进程中需要close关闭accpet返回的新文件描述符)

    • 系统内创建进程个数(与内存大小相关)

    • 进程创建过多是否降低整体服务性能(进程调度)


            


    .server代码[实际开发中要特别注意函数调用返回值判断]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <ctype.h>
 
/*
 * 多进程并发服务器
 * author: sea time 2016/06/18
 */
 
#define SERV_PORT 9096            //服务器端口号
#define SERV_ADDR "10.10.101.102" //服务器ip地址
 
void wait_process(int num){
    //回收子进程
    while(0 < waitpid(0, NULL, WNOHANG)){
        ;
    }
}
 
int main(int argc, char* argv[]){
    pid_t          pid;        //创建进程使用
    int            lfd;        //监听套接字
    int            cfd;        //客户端套接字
    struct sockaddr_in    serv_addr;  //服务器地址族结构体, 绑定使用
    struct sockaddr_in    clie_addr;  //客户端地址族结构体,接收连接使用
    socklen_t      clie_addr_len;  //客户端地址族大小,接收连接使用
    char            buf[BUFSIZ];
    int n, i;
 
    //注册进程结束信号,回收结束的子进程
    signal(SIGCHLD, wait_process);
 
    //创建监听套接字
    //AF_INET:  指定ipv4
    //SOCK_STREAM:  指定tcp
    //0:        函数会根据指定的类型来自动指定协议
    lfd = socket(AF_INET, SOCK_STREAM, 0);
     
    //全部初始化为0
    bzero(&serv_addr, sizeof(serv_addr));
    //指定族:ipv4
    serv_addr.sin_family = AF_INET;  
    //指定ip地址并转换为网络字节序
    inet_pton(AF_INET, SERV_ADDR, &serv_addr.sin_addr.s_addr);
    //指定端口号并转换为网络字节序
    serv_addr.sin_port = htons(SERV_PORT);
    //绑定到监听套接字
    bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
 
    //指定监听套接字并设置同时连接上限
    //SOMAXCONN: 系统默认为128
    listen(lfd, SOMAXCONN);
 
    //循环获取连接
    while(1){
        clie_addr_len = sizeof(clie_addr);
        //阻塞获取连接
        cfd = accept(lfd, (struct sockaddr*)&clie_addr, &clie_addr_len);
        //打屏提示连接成功
        printf("%s:%d connected successfully!\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, buf, sizeof(buf)), ntohs(clie_addr.sin_port));
        //创建进程
        pid = fork();
        //子进程
        if(0 == pid){
            //子进程关闭监听套接字
            close(lfd);
            break;
        }
        //父进程关闭连接套接字
        close(cfd);
    }
 
    //子进程与客户端进程通信 
    while(0 == pid){
        bzero(buf, sizeof(buf));
        //读取客户端发来的消息 
        n = read(cfd, buf, sizeof(buf));
        //客户端关闭的情况下
        if(0 == n){
            close(cfd);
            printf("%s:%d disconnect successfully!\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, buf, sizeof(buf)), ntohs(clie_addr.sin_port));
            exit(1);
        }
        //转换为大小
        for(i = 0; i < n; i++){
            buf[i] = toupper(buf[i]);
        }
        //回写给客户端
        write(cfd, buf, n);
    }
 
    return 0;
}

.client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>
 
/*
 * socket客户端连接服务器
 */
 
#define SERV_PORT 9096            //服务器port
#define SERV_ADDR "10.10.101.102" //服务器ip
 
int main(int argc, char* agrv[]){
    int sfd;  
    struct sockaddr_in serv_addr;
    char buf[BUFSIZ];
    int n;
 
    //创建网络套接字
    //AF_INET:  指定ipv4
    //SOCK_STREAM:  指定tcp
    //0:        函数会根据指定的类型来自动指定协议
    sfd = socket(AF_INET, SOCK_STREAM, 0);
 
    //初始化
    bzero(&serv_addr, sizeof(serv_addr));
    //指定族
    serv_addr.sin_family = AF_INET;
    //指定ip地址并转换为网络字节序
    inet_pton(AF_INET, SERV_ADDR, &serv_addr.sin_addr.s_addr);
    //指定端口并转换为网络字节序
    serv_addr.sin_port = htons(SERV_PORT);
    //连接服务器
    connect(sfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
     
    //读取键盘输入
    while(fgets(buf, sizeof(buf), stdin) != NULL){
        //写服务器发送数据
        write(sfd, buf, strlen(buf));
        bzero(buf, sizeof(buf));
        //读取服务器发来数据
        n = read(sfd, buf, sizeof(buf));
        //服务器关闭
        if(0 == n){
            close(sfd);
            break;
        }
        //向屏幕输出
        write(STDOUT_FILENO, buf, n);
        bzero(buf, sizeof(buf));
    }
}



      本文转自asd1123509133 51CTO博客,原文链接:http://blog.51cto.com/lisea/1790697,如需转载请自行联系原作者