reactor处理大数据

用链表保存fd
这样就涉及到了,链表的扩容,插入,轮询
首先
1.fd的结构体

struct sock_item { // conn_item

	int fd; // clientfd

	char *rbuffer;
	int rlength; //

	char *wbuffer;
	int wlength;
	
	int event;

	void (*recv_cb)(int fd, char *buffer, int length);
	void (*send_cb)(int fd, char *buffer, int length);

	void (*accept_cb)(int fd, char *buffer, int length);

};

2.reactor的保存
这里reactor 存储epoll,链表的头和链表的块数,也就是当前容量

struct reactor {
	int epfd; //epoll
	int blkcnt;

	struct eventblock *evblk; 
};

3.链表的扩容
找到最后面,然后创建一个新的块放到最后
// 扩容

int reactor_resize(struct reactor *r) { // new eventblock

	if (r == NULL) return -1;	

	struct eventblock *blk = r->evblk;

	while (blk != NULL && blk->next != NULL) {
		blk = blk->next;
	}

	struct sock_item* item = (struct sock_item*)malloc(ITEM_LENGTH * sizeof(struct sock_item));
	if (item == NULL) return -4;// 获取失败
	memset(item, 0, ITEM_LENGTH * sizeof(struct sock_item));

	printf("-------------\n");
	struct eventblock *block = malloc(sizeof(struct eventblock));
	if (block == NULL) {// 创建空间失败
		free(item);
		return -5;
	}
	memset(block, 0, sizeof(struct eventblock));

	block->items = item;
	block->next = NULL;

	if (blk == NULL) {
		r->evblk = block;
	} else {
		blk->next = block;
	}
	r->blkcnt ++;

	return 0;
}

4.链表的轮询
先确定是哪个块, 当前fd对块长度取余确定,确定后直接找到位置。

struct sock_item* reactor_lookup(struct reactor *r, int sockfd) {

	if (r == NULL) return NULL;
	//if (r->evblk == NULL) return NULL;
	if (sockfd <= 0) return NULL;

	printf("reactor_lookup --> %d\n", r->blkcnt); //64
	int blkidx = sockfd / ITEM_LENGTH;
	while (blkidx >= r->blkcnt) {
		reactor_resize(r);
	}

	int i = 0;
	struct eventblock *blk = r->evblk;
	while (i ++ < blkidx && blk != NULL) {
		blk = blk->next;
	}

	return  &blk->items[sockfd % ITEM_LENGTH];
}

5.main函数
5.1对reactor进行初始化

struct reactor *r = (struct reactor*)calloc(1, sizeof(struct reactor));
	if (r == NULL) {
		return -3;
	}
	//memset();

	r->epfd = epoll_create(1);
	struct epoll_event ev, events[EVENTS_LENGTH];

5.2socket初始化,创建监听

int init_server(short port) {

	int listenfd = socket(AF_INET, SOCK_STREAM, 0);  // 
	if (listenfd == -1) return -1;
// listenfd
	struct sockaddr_in servaddr;
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(port);

	if (-1 == bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {
		return -2;
	}

#if 1 // nonblock
	int flag = fcntl(listenfd, F_GETFL, 0);
	flag |= O_NONBLOCK;
	fcntl(listenfd, F_SETFL, flag);
#endif

	listen(listenfd, 10);

	return listenfd;
}
int sockfds[PORT_COUNT] = {0};
	int i = 0;
	for (i = 0;i < PORT_COUNT;i ++) {
		sockfds[i] = init_server(9999 + i);

		ev.events = EPOLLIN;
		ev.data.fd = sockfds[i]; //

		epoll_ctl(r->epfd, EPOLL_CTL_ADD, sockfds[i], &ev);
	}

5.2epoll开始监听事件

int nready = epoll_wait(r->epfd, events, EVENTS_LENGTH, -1); // -1, ms 
		//printf("------- %d\n", nready);
		
		int i = 0;
		for (i = 0;i < nready;i ++) {
			int clientfd = events[i].data.fd;
			
			if (is_listenfd(sockfds, clientfd)) { // accept

				struct sockaddr_in client;
				socklen_t len = sizeof(client);
				int connfd = accept(clientfd, (struct sockaddr*)&client, &len);
				if (connfd == -1) break;
				
				if (connfd % 1000 == 999) {
				
					printf("accept: %d\n", connfd);

				}

5.3 将fd加入epoll处理

				ev.events = EPOLLIN;// 读事件
				ev.data.fd = connfd;
				epoll_ctl(r->epfd, EPOLL_CTL_ADD, connfd, &ev);

5.4 读事件处理

else if (events[i].events & EPOLLIN) { //clientfd

				//char rbuffer[BUFFER_LENGTH] = {0};

				struct sock_item *item = reactor_lookup(r, clientfd);

				char *rbuffer = item->rbuffer;
				char *wbuffer = item->wbuffer;
				
				int n = recv(clientfd, rbuffer, BUFFER_LENGTH, 0);
				if (n > 0) {
					//rbuffer[n] = '\0';

					printf("recv: %s, n: %d\n", rbuffer, n);

					memcpy(wbuffer, rbuffer, BUFFER_LENGTH);
					// 将数据读取

					ev.events = EPOLLOUT; 
					// 修改为写事件,因为 模式就是 写-听-读
					ev.data.fd = clientfd;

					epoll_ctl(r->epfd, EPOLL_CTL_MOD, clientfd, &ev);
					
				}
				else if (n == 0) { // 表示断开连接了,直接清空

					free(rbuffer);
					free(wbuffer);
					
					item->fd = 0;

					close(clientfd);
				}

5.5 写事件处理
else if (events[i].events & EPOLLOUT) {

		//先找到fd的结构体,获取要发送的信息,然后发送
		struct sock_item *item = reactor_lookup(r, clientfd);
		char *wbuffer = item->wbuffer;
		
		int sent = send(clientfd, wbuffer, BUFFER_LENGTH, 0); //
		printf("sent: %d\n", sent);

		ev.events = EPOLLIN;
		ev.data.fd = clientfd;

		epoll_ctl(r->epfd, EPOLL_CTL_MOD, clientfd, &ev);
		
		
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值