poll实现多路IO

  1. 源码地址:https://github.com/whuwzp/linuxc/tree/master/poll
  2. 源码说明:
    • server.cpp: 监听127.1:6666,功能是将收到的小写转大写
    • include/wrap.cpp: 封装的一些socket基本操作,加了基本的错误处理

1. 概要

一定先select实现,poll是select的改进版:,有以下不同

  1. 输入输出参数方面

    • select: 需要allfds和readfds两个集合,因为readfds作为输入输出参数,每次select前都要用allfds赋值给它
    • poll: pollfd结构体中,有events和revents两个,分别用来表示输入输出
  2. 监听集合的形式
    • select: 用fd_set位图标记需要监听的fd
    • poll: 用pollfd结构体中的fd成员标记,用结构体数组表示需要监听的集合
  3. 监听信号类型
    • select: 用readfds, writefds集合分别表示
    • poll: 用POLLIN,POLLOUT表示,fds[0].events = POLLIN
  4. 判断是否有信号
    • select: 用FD_ISSET(fd,readfds)
    • poll: 用fds[0].revents & POLLIN

2. 核心代码

#include "include/wrap.h"
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netinet/in.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdnoreturn.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <unistd.h>
#include <wait.h>
#define LOCALIP "127.0.0.1"
#define PORT 6666 void handler(char *in, char *out) {
for (int i = 0; i < (int)strlen(out) + 1; ++i) {
out[i] = toupper(in[i]);
}
} int workthread(const int &fd_client) {
char recvbuf[2048] = {0};
char sendbuf[2048] = {0};
int ret = 0; ret = (int)Read(fd_client, recvbuf, 2048);
if (ret <= 0) {
printf("ret==0\n");
return ret;
} handler(recvbuf, sendbuf); ret = (int)Write(fd_client, sendbuf, strlen(sendbuf) + 1);
return ret;
} void startsock(int &fd, struct sockaddr_in &addr, const char *ip,
const int port) {
fd = Socket(AF_INET, SOCK_STREAM, 0);
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip);
addr.sin_port = htons(port);
}
int main() {
int fd_server = 0;
int fd_client = 0;
int ret = 0;
struct sockaddr_in sock_client;
struct sockaddr_in sock_server;
socklen_t client_len = (socklen_t)sizeof(sock_client);
int opt = 0;
struct pollfd fds[FD_SETSIZE];
int maxi = 0;
int nselect = 0;
int i = 0; startsock(fd_server, sock_server, LOCALIP, PORT);
opt = 1;
Setsockopt(fd_server, SOL_SOCKET, SO_REUSEADDR, &opt,
(socklen_t)sizeof(opt));
Bind(fd_server, (struct sockaddr *)&sock_server, sizeof(sock_server));
Listen(fd_server, 5); for (i = 0; i < FD_SETSIZE; ++i) {
fds[i].fd = -1;
fds[i].events = POLLIN;
}
fds[0].fd = fd_server;
maxi = 0; while (true) {
printf("polling...\n");
nselect = poll(fds, (unsigned long)maxi+1, -1);
if (nselect == -1) {
if (errno == EINTR) {
continue;
} else {
perror_exit("poll failed");
}
}
printf("get %d select\n", nselect);
if (fds[0].revents & POLLIN) {
fd_client =
Accept(fd_server, (struct sockaddr *)&sock_client, &client_len);
printf("accept: %s: %d\n", inet_ntoa(sock_client.sin_addr),
ntohs(sock_client.sin_port));
for (i = 0; i < FD_SETSIZE; ++i) {
if (fds[i].fd != -1) continue;
fds[i].fd = fd_client;
break;
}
printf("i: %d, FD_SETSIZE: %d\n", i, FD_SETSIZE);
if (i == FD_SETSIZE) perror_exit("too many clients");
if (i > maxi) maxi = i;
nselect--;
}
printf("going to find client, maxi: %d, nselect: %d\n", maxi, nselect);
for (i = 0; (i <= maxi) && (nselect > 0); ++i) {
if (!( fds[i].revents & POLLIN )) continue;
printf("find client %d\n", i + 1);
ret = workthread(fds[i].fd);
if (ret <= 0) {
Close(fds[i].fd);
fds[i].fd = -1;
}
nselect--;
}
sleep(3);
}
Close(fd_server);
for (i = 0; i < FD_SETSIZE; ++i) {
if (fds[i].fd == -1) continue;
Close(fds[i].fd);
}
}

3. 参考网址

  1. https://www.bilibili.com/video/av53016117

最新文章

  1. [Android] Visual Studio Emulator For Android 相关
  2. 排序系列 之 简单选择排序及其改进算法 —— Java实现
  3. _fastcall
  4. Java BigDecimal详解
  5. Team Foundation Server 2010下载安装配置方法
  6. OC基础 单例
  7. 受众定向-Topic Model
  8. 每天一个linux命令(38)--lsof命令
  9. 电脑IP地址被占用如何释放?
  10. Java进阶(三十九)Java集合类的排序,查找,替换操作
  11. Python——内置函数
  12. vue 环境的搭建及初始化项目
  13. django csrf_protect及浏览器同源策略
  14. hadoop内存配置方案
  15. Pytorch-学习记录 卷积操作 cnn output_channel, etc.
  16. headpq
  17. Clojure 学习入门(14)—— 循环控制
  18. C#语言-NPOI.dll导入Excel功能的实现
  19. c++之随堂笔记
  20. mongo 聚合

热门文章

  1. 使用C#+EmguCV处理图像入门(一)
  2. Natas0 Writeup(前端源码、敏感信息)
  3. 洛谷3388 tarjan割点
  4. java常用容器简要性能分析(List。Map。Set)
  5. 滑动窗口-Moving Stones Until Consecutive II
  6. 2.Django与Vue的结合
  7. 【笔记3-31】Python语言基础-元组tuple
  8. 学霸双胞胎开源斯坦福CS 221人工智能备忘录,图文并茂看懂反射、状态、变量、逻辑...
  9. 模块 string 常用序列字符
  10. Coding 是门技术