网络编程(二):基于Reactor模型实现服务器百万并发


一、Reactor是什么?

Reactor基本原理

  1. Reactor是一种事件驱动机制,用于同步IO。将I/O操作的并发处理从单线程中分离出来,使程序可以同时处理多个客户端请求.
  2. 由io管理转变为对事件进行管理,不同的io事件对应不同的回调函数,每一个io独立封装
register(注册对应的事件,比如read、write、send…)
callback(根据不同事件调用不同回调函数)

Reactor针对业务的优点

  1. 高效 :通过事件驱动机制,避免了传统的线程池或者进程池带来的资源消耗。
  2. 可扩展:适合高并发、低延迟的场景,如高性能的Web服务器、分布式系统、数据库连接池等高效处理事件的场景。
  3. 简化多线程并发控制:通常在单线程或少数线程中工作,简化了多线程的同步问题。
    在这里插入图片描述

二、服务器百万并发(基于Reactor)

源码

reactor.c

#include <errno.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <poll.h>
#include <sys/epoll.h>
#include <errno.h>
#include <sys/time.h>

#include "server.h"

#define CONNECTION_SIZE			1048576 // 1024 * 1024
#define MAX_PORTS			20
#define TIME_SUB_MS(tv1, tv2)  ((tv1.tv_sec - tv2.tv_sec) * 1000 + (tv1.tv_usec - tv2.tv_usec) / 1000)

// BUFFER_LENGTH:    用于存储读取和写入数据的缓冲区大小
// CONNECTION_SIZE:  最大连接数
// MAX_PORTS:        最大监听的端口数
// TIME_SUB_MS        宏用于计算两个 struct timeval 类型的时间差(单位为毫秒)

int accept_cb(int fd);
int recv_cb(int fd);
int send_cb(int fd);


int epfd = 0;           //epoll 实例的文件描述符
struct timeval begin;   //以 fd 为下标的连接数组,用于快速查找连接信息

struct conn conn_list[CONNECTION_SIZE] = {
   
   0}; //conn结构体 用来描述每个fd连接的状态

/*
功能:向 epoll 实例中添加或修改事件
//根据 flag 的值,决定是添加事件(EPOLL_CTL_ADD)还是修改事件(EPOLL_CTL_MOD)
//通过 epoll_ctl 系统调用与 epoll 文件描述符 epfd 交互来管理事件
*/
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);
		
	}
}

/*
功能:注册一个新连接,初始化连接信息并添加到 epoll 监听
// event_register 函数用于为一个连接(fd)注册事件并初始化连接的状态(就是注册clientfd)。
// 它设置接收回调函数、发送回调函数,以及连接的读取和写入缓冲区
*/
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建立buffer缓冲区空间,用于数据通信
	memset(conn_list[fd].rbuffer, 0, BUFFER_LENGTH);
	conn_list[fd].rlength = 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值