linux网络编程----->高并发--->多进程并发服务器
在做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.
常见的linux并发服务器模型;
-
-
多进程并发服务器
-
多线程并发服务器
-
select多路I/O转接服务器
-
poll多路I/O转接服务器
-
epool多路I/O转接服务器.
-
本次主要讨论多进程并发服务器模型:
使用多进程并发服务器时要考虑以下几点:
-
-
父进程最大文件描述个数(父进程中需要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,如需转载请自行联系原作者