【高性能网络(2)】采用Reactor网络模型实现HTTP服务器


前言

本文将从Reactor网络模型封装网络层函数出发,实现一个简单的HTTP服务器。


一、事件驱动Reactor的原理与实现

1.1 基本原理

简单理解:
由io管理转变为对事件进行管理,不同的io事件对应不同的回调函数

  1. register(注册对应的事件,比如read、write、send…)
  2. callback(根据不同事件调用不同回调函数)

1.2 Reactor线程模型

根据Reactor的数量和处理资源线程池的数量不同,Reactor模型可以分为三种Reactor线程模型:单Reactor单线程、单Reactor多线程和主从Reactor多线程。

本文将实现最简单的单Reactor单线程模型。

1.3 回调函数封装

对于服务器所用到的几个回调函数进行了封装:
accept、recv、send。

在几个回调函数中有几个不好理解的点:

  1. 在什么时机调用这些回调
    1. 当出现读事件时应该调用recv_cb,即在主函数中循环调用
  2. 在什么时机注册这些回调
    1. 那么什么时候注册回调呢?在调用accept_cb时注册读事件回调。因为需要epoll先监听到事件

event_register

int event_register(int fd, int event) {
   
   
	if (fd < 0) return -1;
	conn_list[fd].fd = fd;
	conn_list[fd].r_action.recv_callback = recv_cb;
	conn_list[fd].send_callback = send_cb;

	memset(conn_list[fd].rbuffer, 0, BUFFER_LENGTH);
	conn_list[fd].rlength = 0;

	memset(conn_list[fd].wbuffer, 0, BUFFER_LENGTH);
	conn_list[fd].wlength = 0;

	set_event(fd, event, 1);
}

int set_event(int fd, int event, int flag) {
   
   
	if (flag) {
   
     // non-zero add
		struct epoll_event ev;
		ev.events = event;
		ev.data.fd = fd;
		epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev);
	} else {
   
     // zero mod
		struct epoll_event ev;
		ev.events = event;
		ev.data.fd = fd;
		epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &ev);	
	}
}

accept_cb

// listenfd(sockfd) --> EPOLLIN --> accept_cb
int accept_cb(int fd) {
   
   
	struct sockaddr_in  clientaddr;
	socklen_t len = sizeof(clientaddr);
	int clientfd = accept(fd, (struct sockaddr*)&clientaddr, &len);
	//printf("accept finshed: %d\n", clientfd);
	if (clientfd < 0) {
   
   
		printf("accept errno: %d --> %s\n", errno, strerror(errno));
		return -1;
	}
	
	event_register(clientfd, EPOLLIN);  // | EPOLLET

	if ((clientfd % 1000) == 0) {
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值