Linux高并发服务器解决方案
来源:互联网 发布:东华软件股票行情 编辑:程序博客网 时间:2024/05/16 01:49
Linux高并发服务器案例演示
在网络通信中,我们常常的服务器经常会受到成千上万的请求提示,而电脑会根据请求建立相对应的socket链接,但是接触过Linux网络编程的人都知道,Linux链接和客户端建立连接,会经过四步(这里以TCP说明)
第一步,创建socket对应的描述符,这里设置好socket的协议类型以及通信类型(TCP/UDP)
#include <sys/types.h>/* See NOTES */
#include<sys/socket.h>
int socket(int domain, int type, int protocol);
具体的使用方法可以使用man手册查看socket函数
第二步,绑定端口,以及相应的ip地址(服务器不用设置)
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
intbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
具体的使用方法可以使用man手册查看bind函数
第三步,监听socket,并且设置最大监听数
#include <sys/types.h> /* SeeNOTES */
#include<sys/socket.h>
int listen(int sockfd, int backlog);
具体的使用方法可以使用man手册查看listen函数
第四步,接受客户端的连接
#include <sys/types.h> /* See NOTES */
#include<sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t*addrlen);
具体的使用方法可以使用man手册查看accept函数
注意:
由于上述四步socket建立链接中,accept是阻塞的,意味着如果有很多人同时发出socket请求的时候,服务器只会接收到一少部分的连接,其他都在阻塞队列排队,甚至丢失!甚至建立链接后一旦涉及服务器读写操作时候,涉及到读写,也是会遇到阻塞的!(假设每个用户连接服务器需要0.1秒,那么10000人连接的话则需要1000秒)这样会让服务器浪费大量时间在阻塞过程,所以我们要做的,就是尽可能的让系统发挥出他的性能,让更多的人能够连接系统,却不用花那么长时间。
具体实现方法:
使用epoll分路技术,让accept不陷入阻塞,当那个客户端发出请求,则处理发出请求的客户端信息,这时候因为客户端发出请求,则必定有读写操作,所以读写操作不用去掉阻塞。
服务器代码:
//模拟接收每个客户端发来的请求后并往dbg.txt文件写入一个字节#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/epoll.h>#include <arpa/inet.h>#include <sys/wait.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <errno.h>#include <unistd.h>#include <stdio.h>#include <signal.h>void sig_handle(int sig){ printf("recv signal :%d\n",sig);}int main(int argc, char * argv[]){ signal(SIGPIPE,sig_handle); if (argc<2) { printf("usage:%s + [count]\n",argv[0]); return 0; } unlink("dbg.txt"); int dbg = open("dbg.txt",O_CREAT|O_APPEND|O_RDWR,0666); int count = atoi(argv[1]); int fd = socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(9988); int ret = bind(fd,(struct sockaddr*)&addr,sizeof(addr)); if (ret ==-1) { perror("bind"); return 0; } listen(fd,250); int is_child_process = 0;//判断在哪个进程中,父进程0,子进程1 for (int i = 0 ; i < count ; i++) { pid_t pid = fork(); if (pid==0) { is_child_process = 1; break; } } struct epoll_event ev; ev.events = EPOLLIN|EPOLLET; ev.data.fd = fd; int epfd = epoll_create(1024);//建立epfd的描述符 int flags = fcntl(fd,F_GETFL); flags |= O_NONBLOCK; fcntl(fd,F_SETFL,flags); epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev); while (1) { struct epoll_event evs[10]; int process_count = epoll_wait(epfd,evs,10,5000); if (process_count == 0) continue;//如果监听的进程都没有事件产生,则再次进入循环,继续监听 for (int i = 0 ; i < process_count ;i++) { if (evs[i].data.fd == fd) { //当进程中的socket描述符是server的socket本身时候,则accept否则就直接操作 int ret = accept(evs[i].data.fd,NULL,NULL); if (ret == -1) { printf("errno:%s",strerror(errno)); //其他错误,直接exit break; } ev.data.fd = ret; epoll_ctl(epfd,EPOLL_CTL_ADD,ret,&ev); } else { //read or write char buf[1024]; int ret = read(evs[i].data.fd,buf,sizeof(buf)); if (ret == -1) { perror("read"); if (errno == EINTR) break; exit(0); } else if (ret == 0) { //normal exit close(evs[i].data.fd); break; } //printf("recv data %s from pid:%d\n",buf,getpid()); write(dbg,"1",1); } } } if (!is_child_process) { for (int i = 0 ; i < count; i ++) { wait(NULL);//等待所有的子进程退出为止 } } return 0;}
测试客户端向服务器发请求代码:
//模拟有20000个客户端同时向服务器发请求#include <sys/types.h>#include <sys/socket.h>#include <unistd.h>#include <arpa/inet.h>#include <sys/wait.h>#include <string.h>#define PROCESS_COUNT 20000void func(int argc,char * argv[]){ int fd =socket(AF_INET,SOCK_STREAM,0); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(9988); addr.sin_addr.s_addr =inet_addr("127.0.0.1"); connect(fd,(structsockaddr*)&addr,sizeof(addr)); if (argc==2) write(fd,argv[1],strlen(argv[1])); else write(fd,"1",1); char buf[1024]; //recv(fd,buf,sizeof(buf),0);} int main(int argc,char *argv[]){ for (int i = 0 ; i <PROCESS_COUNT; i++) { pid_t pid = fork(); if (pid == 0) { func(argc,argv); return 0; } } for (int i = 0 ; i <PROCESS_COUNT; i++) { wait(NULL); } return 0;}
结果分析:不同的电脑测试结果略有不同,我的客户端定义有20000个同时向服务器发请求,结果处理的请求大概有15500左右,不同的电脑最高并发数略有不同。成功的解决了多用户同时向一个服务器发请求的问题
- Linux高并发服务器解决方案
- 高并发解决方案—提升高并发量服务器性能
- 高并发量服务器性能解决方案
- linux服务器调整参数支持高并发
- 高并发Linux服务器的常用配置
- linux c++ 高并发tcp服务器架构
- linux c++ 高并发tcp服务器架构
- linux c++ 高并发tcp服务器架构
- linux下高并发服务器实现
- linux下高并发服务器实现
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- java系统高并发解决方案之图片服务器分离
- JS逻辑与&&中的小细节(逻辑或||)
- Win7配置Nginx+PHP7
- why
- 干货分享!2015“双十一”背后的关键技术盘点
- 软件测试实习0705-正交表
- Linux高并发服务器解决方案
- 朴素贝叶斯
- windbg使用
- android性能,内存优化
- Spring事务管理(1)-初探
- GUI库wxPython学习
- 字符编码
- 【leetcode】1. Two Sum
- 素数筛法