初学reactor

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>
#include <sys/epoll.h>
#include <string.h>
#include <stdlib.h>


#define BUFFER_LENGTH	128
#define EVENTS_LENGTH	128


// listenfd, clientfd
struct sock_item { // conn_item 存储fd相关信息

	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);

};


struct reactor { //  reactor  管理epoll 和fd集合的插件
	int epfd; //epoll

	struct sock_item *items; 
};

// thread --> fd
void *routine(void *arg) {

	int clientfd = *(int *)arg;

	while (1) {
		
		unsigned char buffer[BUFFER_LENGTH] = {0};
		int ret = recv(clientfd, buffer, BUFFER_LENGTH, 0);
		if (ret == 0) {
			close(clientfd);
			break;
			
		}
		printf("buffer : %s, ret: %d\n", buffer, ret);

		ret = send(clientfd, buffer, ret, 0); // 

	}

}

// socket --> 
// bash --> execve("./server", "");
// 
// 0, 1, 2
// stdin, stdout, stderr
int main() {

// block  1.套接字创建初始化
	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(9999);

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

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

	listen(listenfd, 10);

///  **********2.reactor 初始化
	struct reactor *r = (struct reactor*)calloc(1, sizeof(struct reactor));
	if (r == NULL) {
		return -3;
	}
	//memset();
	
	r->items = (struct sock_item*)calloc(EVENTS_LENGTH, sizeof(struct sock_item));
	if (r->items == NULL) return -4;
	
// fd --> epoll 
	r->epfd = epoll_create(1);

 
	/// ************** //
	// 2.2 epoll初始化
	struct epoll_event ev, events[EVENTS_LENGTH];
	ev.events = EPOLLIN;
	ev.data.fd = listenfd; //

	epoll_ctl(r->epfd, EPOLL_CTL_ADD, listenfd, &ev); // 
	

	while (1) { // 7 * 24 
		//3.开始epoll处理
		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 (listenfd == clientfd) { // accept  第一个先处理

				struct sockaddr_in client;
				socklen_t len = sizeof(client);
				int connfd = accept(listenfd, (struct sockaddr*)&client, &len);
				if (connfd == -1) break;
				
				printf("accept: %d\n", connfd);
				ev.events = EPOLLIN; 
				ev.data.fd = connfd;
				epoll_ctl(r->epfd, EPOLL_CTL_ADD, connfd, &ev);
			
				r->items[connfd].rbuffer = calloc(1, BUFFER_LENGTH);
				r->items[connfd].rlength = 0;
				
				r->items[connfd].wbuffer = calloc(1, BUFFER_LENGTH);
				r->items[connfd].wlength = 0;

				r->items[connfd].event = EPOLLIN;
				
			} else if (events[i].events & EPOLLIN) { //clientfd
				//3.1 读事件处理
				// 获取客户端的消息
				//char rbuffer[BUFFER_LENGTH] = {0};

				char *rbuffer = r->items[clientfd].rbuffer;
				char *wbuffer = r->items[clientfd].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;
					// ev.data.fd = clientfd; 完了之后改为发送数据
					epoll_ctl(r->epfd, EPOLL_CTL_MOD, clientfd, &ev);
					
				} 
			// 3.2 写事件处理 也就是发送事件处理
			} else if (events[i].events & EPOLLOUT) {

				char *wbuffer = r->items[clientfd].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、付费专栏及课程。

余额充值