Linux高并发服务器解决方案
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,子进程1for (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));//其他错误,直接exitbreak;}ev.data.fd = ret;epoll_ctl(epfd,EPOLL_CTL_ADD,ret,&ev);}else{//read or writechar 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 exitclose(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 20000
void 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]));elsewrite(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 系统编程 linux 环境的搭建 环境搭建需要的软件 虚拟机中安装 u ...
- Linux高并发服务器开发---笔记2(多进程)
0630 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.2 Linux系统编程1.4.3 Linux系统编程2 4.4 多进程 1-9 10.进程间通信☆☆☆ 进程间 ...
- Linux高并发服务器开发---笔记1(环境搭建、系统编程、多进程)
0613 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.1.1 项目介绍 4.1.2 开发环境搭建 ①安装Linux系统.XSHELL.XFTP.Visual Stu ...
- Linux 高并发服务器实战 - 2 Linux多进程开发
Linux 高并发服务器实战 - 2 Linux多进程开发 进程概述 概念1: 概念2: 微观而言,单CPU任意时刻只能运行一个程序 并发:两个队列交替使用一台咖啡机 并行:两个队列同时使用两台咖啡机 ...
- Linux高并发服务器开发---笔记4(网络编程)
0705 第4章 项目制作与技能提升 4.0 视频课链接 4.1 项目介绍与环境搭建 4.2 Linux系统编程1.4.3 Linux系统编程2 4.4 多进程 1-9 10.进程间通信☆☆☆ 4.5 ...
- [Linux 高并发服务器]网络基础
[Linux 高并发服务器]网络基础 文章概述 该博客为牛客网C++项目课:Linux高并发服务器 个人笔记 作者信息 NEFU 2020级 zsl ID:fishingrod/鱼竿钓鱼干 Email ...
- [Linux 高并发服务器]GDB调试
[Linux 高并发服务器]GDB调试 [Linux 高并发服务器]GDB调试 [Linux 高并发服务器]GDB调试 GDB是什么 预先准备 基本命令 例子 进入和退出gdb 获取帮助 查看文件代码 ...
- Linux 高并发服务器实战 - 1 Linux系统编程入门
Linux 高并发服务器实战-1Linux系统编程入门 在本机和服务器端设置公共密钥(配置免密登录) 在本机cmd里输入 ssh-keygen -t rsa,生成本机的公密钥 在服务器端里也配置 ss ...
- Linux高并发服务器开发—项目实战
1.阻塞/非阻塞.同步/异步(网络IO) 典型的一次IO的两个阶段是什么?数据就绪 和 数据读写 数据就绪:根据系统IO操作的就绪状态 阻塞--非阻塞 数据读写:根据应用程序和内核的交互方式 同步-- ...
最新文章
- Python 自动化-pywinauto库定位树结构控件里的树节点实例演示
- 嵌入式码农的10年Bug调试经验,值得一看
- 伯努利数(详解 + 例题 :P3711 仓鼠的数学题)
- jQuery学习总结06-插件开发
- Socket编程实践(9) --套接字IO超时设置方法
- TypeScript学习(二):任意类型及推论
- TensorFlow 学习(十五)—— tensorflow.python.platform
- 使用samba完成Linux服务器与Windows之间的映射
- android wps mac 下载地址,wps for mac下载
- ansible 远程启动程序ansible结束后程序也被关闭
- 让PS可以保存为ICO格式
- 树莓派使用排线摄像头和远程视频监控
- 空格键 还是 Tab键?
- matlab 色温图,一张图看懂“色温”的通用范围标准!摄影白平衡其实就这么简单...
- JAVA封神榜之九尾妖狐,盘点《封神演义》中的7位散修大妖,孔宣排第三,九尾妖狐排第六...
- 怎么制作珠宝首饰类标签
- 最新2018手机号码正则表达式
- 华为快应用-修改IDE的主题颜色
- 5G PC来了!联想携YOGA 5G笔记本亮相ChinaJoy
- PHP开发的简洁的导航网站源码多种主题风格切换