实现TCP并发服务器之四(poll函数)

poll函数类似于select函数,但是它的程序员接口不同,尽管它也可用于任何类型 文件描述符。与select不同,poll不为每个状态(可读,可写,异常状态)构造一个描述符集,而是构造一个pollfd结构数组,每个数组元素指定一个描述符编号以及对其所关心的状态

struct pollfd {
	int fd;				//file descriptor to check
	short events;		//events of interest on fd
	short revents;		//events that occured on fd
};
同样实现一个TCP服务器看看。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/poll.h>
#include<limits.h>

#define MAX_LISTEN 5
#define PORT 1987
#define IP "127.0.0.1"

#define MAX_POLL 100

//#define POLLRDNORM 0x0040

int main()
{
	int conn_fd;
	int sock_fd = socket(AF_INET,SOCK_STREAM,0);
	if (sock_fd < 0) {
		perror("create socket failed");
		exit(1);
	}

	struct sockaddr_in addr_client;
	int client_size = sizeof(struct sockaddr_in);

	struct sockaddr_in addr_serv;
	memset(&addr_serv, 0, sizeof(addr_serv));
	addr_serv.sin_family = AF_INET;
	addr_serv.sin_port = htons(PORT);
	addr_serv.sin_addr.s_addr = inet_addr(IP);

	if (bind(sock_fd,(struct sockaddr *)&addr_serv,sizeof(struct sockaddr_in)) < 0) {
		perror("bind error");
		exit(1);
	}

	if (listen(sock_fd,MAX_LISTEN) < 0) {
		perror("listen failed");
		exit(1);
	}

	//
	int recv_num;
	int send_num;
	char recv_buf[100];
	char send_buf[100];	

	//initial "poll" elements
	int i, ready;
	struct pollfd client[MAX_POLL];

	client[0].fd = sock_fd;
	client[0].events = POLLRDNORM;
	for (i = 1;i < MAX_POLL; i ++) {
		client[i].fd = -1;
	}
	int maxi = 0;


	while (1) {

		ready = poll(client, maxi + 1, 0);
		
		//create new connection
		if (client[0].revents & POLLRDNORM) {
			conn_fd = accept(sock_fd, (struct sockaddr *)&addr_client, &client_size);
			if (conn_fd < 0) {
				perror("accept failed");
				exit(1);
			}

			for (i = 1;i < MAX_POLL;i ++) {
				if (client[i].fd < 0) {
					client[i].fd = conn_fd;
					break;
				}
			}
			if (i == MAX_POLL) {
				perror("too many clients");
				exit(1);
			}

			if (i > maxi)
				maxi = i;
		}
		
		//send and receive
		for (i = 1; i <= maxi; i ++) {
			if (client[i].fd >= 0 && (client[i].revents & (POLLRDNORM | POLLERR))) {

				recv_num = recv(client[i].fd, recv_buf, sizeof(recv_buf), 0);
				if (recv_num <= 0) {
					close(client[i].fd);
					client[i].fd = -1;
				} else {
					recv_buf[recv_num] = '\0';
					memset(send_buf,0,sizeof(send_buf));
					sprintf(send_buf, "server proc got %d bytes\n", recv_num);
					send_num = send(client[i].fd, send_buf, strlen(send_buf), 0);
					if (send_num <= 0) {
						close(client[i].fd);
						client[i].fd = -1;
					}
				}
			}
		}
	}
		
	close(sock_fd);
	return 0;
}

其实poll函数和select函数差不多的,都是在获取可用描述符处等待,只是select的文件描述符数目受限于操作系统内核设定,我感觉poll函数用起来更加方便些,每个人都各有所好吧。接下来再看看epoll函数

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值