在做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.
常见的linux并发服务器模型;多进程并发服务器
多线程并发服务器
select多路I/O转接服务器
poll多路I/O转接服务器
epool多路I/O转接服务器.
本次主要讨论多进程并发服务器模型:
使用多进程并发服务器时要考虑以下几点:父进程最大文件描述个数(父进程中需要close关闭accpet返回的新文件描述符)
系统内创建进程个数(与内存大小相关)
进程创建过多是否降低整体服务性能(进程调度)
.server代码[实际开发中要特别注意函数调用返回值判断]#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/*
* 多进程并发服务器
*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
;
}
}
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;//客户端地址族大小,接收连接使用
charbuf[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
buf[i] = toupper(buf[i]);
}
//回写给客户端
write(cfd, buf, n);
}
return 0;
}
.client#include
#include
#include
#include
#include
#include
#include
/*
* 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));
}
}