POLL机制示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> /* superset of previous */

#include <poll.h>

/* 定义服务器初始化函数 */
int server_init(char *ip, short port)
{
	int ret;
	int listenfd;
	struct sockaddr_in srvaddr;

	/* 创建套接字文件 */
	listenfd = socket(AF_INET, SOCK_STREAM, 0);
	if (listenfd == -1) {
		perror("server_init->socket");
		return -1;
	}
	printf("listenfd = %d\n", listenfd);

	/* 绑定服务器的ip地址和端口号 */
	memset(&srvaddr, 0, sizeof(srvaddr));
	srvaddr.sin_family = AF_INET;
	srvaddr.sin_port = htons(port);
	if (ip == NULL) 
		srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	else 
		srvaddr.sin_addr.s_addr = inet_addr(ip);
	ret = bind(listenfd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));
	if (ret == -1) {
		perror("server_init->bind");
		return -1;
	}
	printf("bind success\n");

	/* 启动监听 */
	ret = listen(listenfd, 1024);
	if (ret == -1) {
		perror("server_init->listen");
		return -1;
	}

	return listenfd;
}

/* 定义服务器等待客户端的连接请求,建立连接 */
int server_wait_client_connect(int listenfd)
{
	int connfd;
	socklen_t addrlen;
	struct sockaddr_in cltaddr;

	//accept(listenfd, NULL, NULL);
	addrlen = sizeof(cltaddr);
	connfd = accept(listenfd, (struct sockaddr *)&cltaddr, &addrlen);
	if (connfd == -1) {
		perror("accept");
		return -1;
	}
	printf("IP : %s connet success connfd = %d\n", inet_ntoa(cltaddr.sin_addr), connfd);

	return connfd;
}



int main()
{
	int ret;
	int listenfd;
	int connfd;
	char buf[256];
	int nfds;
	int i;
	int j;
	int fd;
	struct pollfd fds[128];


	/* 1. 服务器的初始化 */
	listenfd = server_init("127.0.0.1", 8888);
	//listenfd = server_init(NULL, 8888);
	if (listenfd == -1)
		exit(EXIT_FAILURE);
	printf("server init success\n");

	/* 创建集合,清空集合 */
	for (i = 0; i < 128; i++)
		fds[i].fd = -1;

	/* 将文件描述符listenfd及其对应事件添加到集合fds中 */
	fds[0].fd = listenfd;
	fds[0].events = POLLIN;
	nfds = 1;

	while(1) {
		/* c, 调用poll函数,检测是否有准备就绪的事件,如果没有事件准备就绪,函数一直阻塞。如果有事件准备就绪函数返回;*/
		ret = poll(fds, nfds, 5000);
		if (ret == -1) {
			perror("poll");
			return -1;
		} else if (ret == 0) {
			printf("timeout ......\n");
			continue;
		}
		
		for (i = 0; i < nfds; i++) {
			/* 读资源准备就绪,进行读IO操作 */
			if (fds[i].revents == POLLIN) {
				fd = fds[i].fd;
				if (fd == listenfd) { 	/* 监听套接字 */
					/* 2. 服务器等待客户端的连接请求,建立连接 */
					connfd = server_wait_client_connect(listenfd);
					if (connfd == -1)
						exit(EXIT_FAILURE);
					/* 连接成功,将文件描述符connfd及其对应事件添加到集合fds中 */
					fds[nfds].fd = connfd;
					fds[nfds].events = POLLIN;
					nfds ++;
					continue;
				} //if (fd == listenfd) end

				/* 通信套接字 */
				/* 3. 服务器处理客户端的数据请求,并处理数据,反馈处理结果 */
				memset(buf, 0, sizeof(buf));
				ret = read(fd, buf, sizeof(buf));
				if (ret == -1) {
					perror("server->read");
					return -1;
				} else if (ret == 0) {
					/* 客户端退出的时候,需要将套接字从集合中删除 */
					for (j = i; j < nfds-1; j++)
						fds[j] = fds[j+1];
					close(fd);
					break;
				}
				printf("buf : %s\n", buf);

				ret = write(fd, buf, sizeof(buf));
				if (ret == -1) {
					perror("server->write");
					return -1;
				}
			} //if (fds[i].revents == POLLIN) end
			if (fds[i].events == POLLOUT) {
				/* 执行写IO操作 */
			}

		} //for (fd = 0; fd < nfds; fd++) end
	} //while(1) end

	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux中的poll机制是一种IO多路复用的机制,它可以同时监视多个文件描述符的可读、可写和异常等事件。当有文件描述符就绪时,poll会通知应用程序进行相应的操作。 poll机制的工作原理如下: 1. 应用程序调用poll函数,并传入一个pollfd结构体数组,每个结构体包含一个文件描述符和要监视的事件。 2. poll函数将这个数组传递给内核,并阻塞等待事件发生。 3. 当有文件描述符就绪时,内核会修改pollfd结构体中的revents字段,表示该文件描述符的就绪事件。 4. poll函数返回,应用程序可以通过遍历pollfd数组来找到就绪的文件描述符,并进行相应的操作。 与select机制相比,poll机制的改进之处在于: 1. poll没有最大文件描述符数量的限制,可以处理更多的文件描述符。 2. poll使用pollfd结构体数组来传递文件描述符和事件,更加灵活。 示例代码如下: ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <poll.h> int main() { struct pollfd fds[1]; int ret; // 打开一个文件描述符 int fd = open("test.txt", O_RDONLY); // 设置要监视的文件描述符和事件 fds[0].fd = fd; fds[0].events = POLLIN; // 调用poll函数等待事件发生 ret = poll(fds, 1, -1); if (ret == -1) { perror("poll"); exit(EXIT_FAILURE); } // 检查文件描述符的就绪事件 if (fds[0].revents & POLLIN) { printf("File descriptor is ready for reading.\n"); } // 关闭文件描述符 close(fd); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值