做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.
常见的linux并发服务器模型;
多进程并发服务器
多线程并发服务器
select多路I/O转接服务器
poll多路I/O转接服务器
epool多路I/O转接服务器.
本次主要讨论多线程并发服务器模型:
使用多线程模型开发服务时需要考虑以下问题
1. 调整进程内最大文件描述符上限.
2. 线程如有共享数据, 考虑线程同步.
3. 服务于客户端线程退出时, 退出处理(退出值, works线程处于分离态)
4. 系统负载, 随着链接客户的增加, 导致其它线程不能级时得到CPU
.server代码[实际开发中要特别注意函数调用返回值判断]
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <pthread.h>
/*
* 多线程并发服务器
* author sea time 2016/06/20
*/
#define SERV_PORT 9096 //服务所占用端口
#define SERV_ADDR "10.10.101.105" //服务所占用ip
//线程处理函数
void* thread_handler(void* args){
char buf[BUFSIZ]; //BUFSIZ 内置宏 8192
int n, i;
int fd = (int)args; //转换获得客户端描述符
while(1){
bzero(buf, sizeof(buf));
n = read(fd, buf, sizeof(buf));
//对方已关闭
if(0 == n){
//关闭连接
close(fd);
printf("close...\n");
break;
}else if(0 < n){
//大小写转换
for(i = 0; i < n; i++){
buf[i] = toupper(buf[i]);
}
//发送给客户端
write(fd, buf, n);
}
}
pthread_exit(NULL);
}
int main(int argc, char* argv[]){
pthread_t tid;
int listenfd, connfd;
struct sockaddr_in serv_addr, clie_addr;
socklen_t clie_addr_len;
int opt;
char str[INET_ADDRSTRLEN]; //INET_ADDRSTRLEN 内存宏 16
//创建监听套接字
//AF_INET: ipv4
//SOCK_STREAM tcp流类型
//IPPROTO_TCP tcp协议
listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
//设置端口复用
opt = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
//初始化为0
bzero(&serv_addr, sizeof(serv_addr));
//指定族: ipv4
serv_addr.sin_family = AF_INET;
//指定端口号并转换成网络字节序
serv_addr.sin_port = htons(SERV_PORT);
//指定ip并转换为网络字节序
inet_pton(AF_INET, SERV_ADDR, &serv_addr.sin_addr.s_addr);
//绑定到监听套接字
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//设置同时连接请求上限
listen(listenfd, SOMAXCONN);
while(1){
clie_addr_len = sizeof(clie_addr);
//阻塞获取连接
connfd = accept(listenfd, (struct sockaddr*)&clie_addr, &clie_addr_len);
//输出连接的客户端信息
printf("%s:%d connect successfully!\n", inet_ntop(AF_INET, &clie_addr.sin_addr.s_addr, str, sizeof(str)), ntohs(clie_addr.sin_port));
//创建线程与之连接处理, 并将描述符给works线程
pthread_create(&tid, NULL, thread_handler, (void*)connfd);
//设置线程分离
pthread_detach(tid);
}
close(listenfd);
return 0;
}
多线程与多进程由模型于在linux当中CPU调试对待一样, 所以在连接数不多的请况下使用多线程和多进程非常方便.
转载于:https://blog.51cto.com/lisea/1791023