linux网络编程----->高并发--->poll多路I/O转接服务器

简介:

做网络服务的时候并发服务端程序的编写必不可少。前端客户端应用程序是否稳定一部分取决于客户端自身,而更多的取决于服务器是否相应时间够迅速,够稳定.

    常见的linux并发服务器模型;


  • 多进程并发服务器

  • 多线程并发服务器

  • select多路I/O转接服务器

  • poll多路I/O转接服务器

  • epool多路I/O转接服务器.


    本次主要讨论poll多路I/转接并发服务器模型:

    wKioL1dlV3ORUbUGAAISrviO-QM731.png-wh_50


    前几章介绍完了多进程并发服务器,  多线程并发服务器selete多路I/O转接服务器,  本章开始介绍poll(linux特有)多路I/O转接模型.

    由于多进程和多线程模型在实现中相对简单, 但由于其开销和CPU高度中比较大, 所以一般不用多线程和多进程来实现服务模型. select由于其跨平台, 但其最高上限默认为1024, 修改突破1024的话需要重新编译linux内核, poll完美解决了1024的限制.


    主要用到API:

        poll(struct pollfd *fds, nfds_t nfds, int timeout);

        fds:  传入传出结构体数组

        nfds: 结构体数组数量

        timeout: 监听时间        

                            -1 阻塞等待

                            0 立刻返回, 不阻塞

                            >0 等待毫秒数

        struct pollfd{

                int fd;              //监听的文件描述符

                int events;      //监听的事件 POLLIN监听读 POLLOUT 监听写 POLLERR 监听异常

                int revents;    // 监听事件中满足条件返回的事件


    .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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>
 
#define CLIENT_MAX 1024       //定义最大客户端监听
#define SERV_PORT 9096        //监听端口
 
int  main( int  argc,  char * argv[]){
     int  listenfd, connfd;
     struct  sockaddr_in serv_addr, clie_addr;
     socklen_t clie_addr_len;
     struct  pollfd event[CLIENT_MAX];
     int  maxi, opt, i, j, nready, n;
     char  buf[BUFSIZ];
     
     //创建tcp监听套接字
     listenfd = socket(AF_INET, SOCK_STREAM, 0);
 
     //设置端口复用
     opt = 1;
     setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt,  sizeof (opt));
 
     //初始化为0
     bzero(&serv_addr,  sizeof (serv_addr));
     serv_addr.sin_family = AF_INET;
     //设置端口并转换为网络字节序
     serv_addr.sin_port = htons(SERV_PORT);
     //设置本机任意ip
     serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
     //绑定listenfd
     bind(listenfd, ( struct  sockaddr*)&serv_addr,  sizeof (serv_addr));
 
     //设置同时连接上限
     listen(listenfd, SOMAXCONN);    //#define SOMAXCONN 128
     
     //将监听套接字连接至事件
     event[0].fd = listenfd;
     event[0].events = POLLIN;
 
     //初始化
     for (i = 1; i < CLIENT_MAX; i++){
         event[i].fd = -1;
     }
 
     maxi = 0;
     for (;;){
         nready = poll(event, maxi+1, -1);
         
         //客户端请求连接
         if (event[0].revents & POLLIN){
             clie_addr_len =  sizeof (clie_addr);
             //获取连接
             connfd = accept(listenfd, ( struct  sockaddr*)&clie_addr, &clie_addr_len);
             //打印提示
             printf ( "%s:%d client connect successfully!\n" , inet_ntoa(clie_addr.sin_addr), ntohs(clie_addr.sin_port));
 
             //添加至监听
             for (i = 1; i < CLIENT_MAX; i++){
                 if (0 > event[i].fd){
                     event[i].fd = connfd;
                     break ;
                 }      
             }
             //判断监听是否已满
             if (CLIENT_MAX == i){
                 //关闭连接
                 printf ( "too many clients!\n" );
                 close(connfd);
                 continue ;
             }
             //监听读事件
             event[i].events = POLLIN;
             if (i > maxi)
                 maxi = i;
 
             if (0 == (--nready))
                 continue ;
         }
 
         for (i = 1; i <= maxi; i++){
             if (0 > event[i].fd)
                 continue ;
 
             //是否有事件
             if (event[i].revents & POLLIN){
                 //清空
                 bzero(buf,  sizeof (buf));
                 n = read(event[i].fd, buf,  sizeof (buf));
                 //对方是否已关闭
                 if (0 == n){
                     clie_addr_len =  sizeof (clie_addr);
                     //获取客户端信息
                     getpeername(event[i].fd, ( struct  sockaddr*)&clie_addr, &clie_addr_len);
                     printf ( "%s:%d client disconnect successfully!\n" , inet_ntoa(clie_addr.sin_addr), ntohs(clie_addr.sin_port));
                     //关闭客户端连接
                     close(event[i].fd);
                     //将事件数组中初始化为-1
                     event[i].fd = -1;
                 } else  if (0 < n){
                     //转换为大写
                     for (j = 0; j < n; j++){
                         buf[j] =  toupper (buf[j]);
                     }
                     //回写给客户端
                     write(event[i].fd, buf, n);
                 }
                 if (0 == (--nready)){
                     break ;
                 }
             }
         }
     }
     close(listenfd);
     return  0; 
}



      本文转自asd1123509133 51CTO博客,原文链接:http://blog.51cto.com/lisea/1791967,如需转载请自行联系原作者





相关文章
|
5月前
|
弹性计算 安全 Linux
阿里云服务器ECS安装宝塔Linux面板、安装网站(新手图文教程)
本教程详解如何在阿里云服务器上安装宝塔Linux面板,涵盖ECS服务器手动安装步骤,包括系统准备、远程连接、安装命令执行、端口开放及LNMP环境部署,手把手引导用户快速搭建网站环境。
|
6月前
|
监控 Linux 网络安全
FinalShell SSH工具下载,服务器管理,远程桌面加速软件,支持Windows,macOS,Linux
FinalShell是一款国人开发的多平台SSH客户端工具,支持Windows、Mac OS X和Linux系统。它提供一体化服务器管理功能,支持shell和sftp同屏显示,命令自动提示,操作便捷。软件还具备加速功能,提升访问服务器速度,适合普通用户和专业人士使用。
2235 0
|
8月前
|
Linux
【Linux】 Linux文件I/O常见操作技巧
以上就是Linux文件I/O操作的一些技巧,接纳它们,让它们成为你在Linux世界中的得力伙伴,工作会变得轻松许多。不过记住,技巧的运用也需要根据实际情况灵活掌握,毕竟,最适合的才是最好的。
256 28
|
8月前
|
数据挖掘 Linux 数据库
服务器数据恢复—Linux系统服务器数据恢复案例
服务器数据恢复环境: linux操作系统服务器中有一组由4块SAS接口硬盘组建的raid5阵列。 服务器故障: 服务器工作过程中突然崩溃。管理员将服务器操作系统进行了重装。 用户方需要恢复服务器中的数据库、办公文档、代码文件等。
|
9月前
|
JavaScript Linux Python
在Linux服务器中遇到的立即重启后的绑定错误:地址已被使用问题解决
总的来说,解决"地址已被使用"的问题需要理解Linux的网络资源管理机制,选择合适的套接字选项,以及合适的时间点进行服务重启。以上就是对“立即重启后的绑定错误:地址已被使用问题”的全面解答。希望可以帮你解决问题。
481 20
|
10月前
|
存储 人工智能 运维
阿里云操作系统控制台——解决服务器磁盘I/O故障
阿里云操作系统控制台——解决服务器磁盘I/O故障
480 12
|
10月前
|
存储 运维 监控
深度体验阿里云系统控制台:SysOM 让 Linux 服务器监控变得如此简单
作为一名经历过无数个凌晨三点被服务器报警电话惊醒的运维工程师,我对监控工具有着近乎苛刻的要求。记得去年那次大型活动,我们的主站流量暴增,服务器内存莫名其妙地飙升到90%以上,却找不到原因。如果当时有一款像阿里云 SysOM 这样直观的监控工具,也许我就不用熬通宵排查问题了。今天,我想分享一下我使用 SysOM 的亲身体验,特别是它那令人印象深刻的内存诊断功能。
390 1
|
10月前
|
Linux 虚拟化 Docker
Linux服务器部署docker windows
在当今软件开发中,Docker成为流行的虚拟化技术,支持在Linux服务器上运行Windows容器。流程包括:1) 安装Docker;2) 配置支持Windows容器;3) 获取Windows镜像;4) 运行Windows容器;5) 验证容器状态。通过这些步骤,你可以在Linux环境中顺利部署和管理Windows应用,提高开发和运维效率。
1628 1
|
安全 大数据 Linux
云上体验最佳的服务器操作系统 - Alibaba Cloud Linux | 飞天技术沙龙-CentOS 迁移替换专场
本次方案的主题是云上体验最佳的服务器操作系统 - Alibaba Cloud Linux ,从 Alibaba Cloud Linux 的产生背景、产品优势以及云上用户使用它享受的技术红利等方面详细进行了介绍。同时,通过国内某社交平台、某快递企业、某手机客户大数据业务 3 大案例,成功助力客户实现弹性扩容能力提升、性能提升、降本增效。 1. 背景介绍 2. 产品介绍 3. 案例分享
310 1
|
存储 Oracle 安全
服务器数据恢复—LINUX系统删除/格式化的数据恢复流程
Linux操作系统是世界上流行的操作系统之一,被广泛用于服务器、个人电脑、移动设备和嵌入式系统。Linux系统下数据被误删除或者误格式化的问题非常普遍。下面北亚企安数据恢复工程师简单聊一下基于linux的文件系统(EXT2/EXT3/EXT4/Reiserfs/Xfs) 下删除或者格式化的数据恢复流程和可行性。