l8-d16 多路复用poll函数

一、poll函数

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

struct pollfd {

int fd; /* 文件描述符 */

short events; /* 请求的事件 */

short revents; /* 返回的事件 */

};

nfds:fds的个数

timeout:设置阻塞的时间(毫秒)

0为非阻塞

负数表示永久阻塞

事件类型

events:

POLLIN:有数据可读

•POLLPRI:有紧急数据需要读取
•POLLOUT: 文件可写

.....

二、poll的实现

头文件

cpp 复制代码
#ifndef _NET_H_
#define _NET_H_

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <strings.h>
#include <errno.h>

typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;
#define BACKLOG 5
#define ErrExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while(0)

void Argment(int argc, char *argv[]);
int CreateSocket(char *argv[]);
int DataHandle(int fd);


#endif

poll实现

cpp 复制代码
#include "net.h"
#include <poll.h>

#define MAX_SOCK_FD 1024
int main(int argc, char *argv[])
{
	int i, j, fd, newfd;
	nfds_t nfds = 1;
	struct pollfd fds[MAX_SOCK_FD] = {};//pollfd结构体数组,用于存储要被监视的文件描述符集合
	Addr_in addr;    //网络地址结构体变量addr
	socklen_t addrlen = sizeof(Addr_in);    //地址长度变量addrlen
	/*检查参数,小于3个 直接退出进程*/
	Argment(argc, argv);    //Argment函数检查命令行参数的合法性
	/*创建已设置监听模式的套接字*/
	fd = CreateSocket(argv);    //创建一个监听套接字
	fds[0].fd = fd;    //将监听套接字fd添加到被监视的文件描述符集合中
	fds[0].events = POLLIN;    //并设置其关注的事件为POLLIN(有数据可读)
	while(1){
		if( poll(fds, nfds, -1) < 0)    //poll函数监视文件描述符集合
			ErrExit("poll");
		for(i = 0; i < nfds; i++){    //遍历所有被监视的文件描述符
			/*接收客户端连接,并生成新的文件描述符*/
			if(fds[i].fd == fd && fds[i].revents & POLLIN){    //如果当前文件描述符等于监听套接字,并且有数据可读,则接收新的客户端连接。
				if( (newfd = accept(fd, (Addr *)&addr, &addrlen) ) < 0)    //accept函数接收客户端连接
					perror("accept");
				fds[nfds].fd = newfd;    //将新的客户端连接添加到被监视的文件描述符集合中
				fds[nfds++].events = POLLIN;    //并设置其关注的事件为POLLIN(有数据可读)
				printf("[%s:%d][nfds=%lu] connection successful.\n", 
						inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), nfds);
			}
			/*处理客户端数据*/
			if(i > 0 && fds[i].revents & POLLIN){    //如果当前文件描述符不是监听套接字,并且有数据可读,则处理客户端数据
				if(DataHandle(fds[i].fd) <= 0){
					if( getpeername(fds[i].fd, (Addr *)&addr, &addrlen) < 0)
						perror("getpeername");
					printf("[%s:%d][fd=%d] exited.\n", 
							inet_ntoa(addr.sin_addr), ntohs(addr.sin_port), fds[i].fd);
					close(fds[i].fd);
					for(j=i; j<nfds-1; j++)
						fds[j] = fds[j+1];
					nfds--;
					i--;
				}
			}
		}
	}
	close(fd);
	return 0;
}

封装函数

cpp 复制代码
#include "net.h"

void Argment(int argc, char *argv[]){
	if(argc < 3){
		fprintf(stderr, "%s<addr><port>\n", argv[0]);
		exit(0);
	}
}
int CreateSocket(char *argv[]){
	/*创建套接字*/
	int fd = socket(AF_INET, SOCK_STREAM, 0);
	if(fd < 0)
		ErrExit("socket");
	/*允许地址快速重用*/
	int flag = 1;
	if( setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag) ) )
		perror("setsockopt");
	/*设置通信结构体*/
	Addr_in addr;
	bzero(&addr, sizeof(addr) );
	addr.sin_family = AF_INET;
	addr.sin_port = htons( atoi(argv[2]) );
	/*绑定通信结构体*/
	if( bind(fd, (Addr *)&addr, sizeof(Addr_in) ) )
		ErrExit("bind");
	/*设置套接字为监听模式*/
	if( listen(fd, BACKLOG) )
		ErrExit("listen");
	return fd;
}
int DataHandle(int fd){
	char buf[BUFSIZ] = {};
	Addr_in peeraddr;
	socklen_t peerlen = sizeof(Addr_in);
	if( getpeername(fd, (Addr *)&peeraddr, &peerlen) )
		perror("getpeername");
	int ret = recv(fd, buf, BUFSIZ, 0);
	if(ret < 0)
		perror("recv");
	if(ret > 0){
		printf("[%s:%d]data: %s\n", 
				inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port), buf);
	}
	return ret;
}
相关推荐
find1star7 小时前
LeetCode 141:环形链表
java·算法·leetcode·链表
迅翼SwiftWing7 小时前
编队系列(总)|固定翼编队如何实现稳定飞行?通信架构、协同算法与工程约束深度解析
算法·架构
LB21127 小时前
力扣160 21 86
算法·leetcode·职场和发展
小智老师PMP8 小时前
2026深度解析|PMP第八版与NPDP核心侧重点本质区别(管理类证书怎么选)
开发语言·分布式·算法·职场和发展·产品经理
HugoStudio_SWAN9 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
a187927218319 小时前
【算法】动态规划第二篇:双序列 DP 三课——继承、计步与断链
算法·leetcode·动态规划·dp·回溯·暴力·算法讲解
江畔柳前堤10 小时前
前台·中台·后台:2026年AI原生时代的架构全景图
开发语言·人工智能·算法·机器学习·架构·scala·ai-native
文心快码BaiduComate10 小时前
2026 OPC x AI Coding 趋势案例交流会圆满落幕:一个人就一支研发团队
算法
ACM-moran10 小时前
条件显化(二分单峰函数+构造数列)
算法·推公式·整数三分
闻缺陷则喜何志丹11 小时前
【栈 运算系统】P3719 [AHOI2017初中组] rexp|普及+
c++·算法··洛谷·运算系统