code_tin

从头编写高性能服务程序11-指令处理&sendfile
实现命令的获取之后 现在是增加对command的解析以及对应的反馈 为了做些稍微有意义的事情.我把这个servic...
扫描右侧二维码阅读全文
02
2010/02

从头编写高性能服务程序11-指令处理&sendfile

实现命令的获取之后
现在是增加对command的解析以及对应的反馈
为了做些稍微有意义的事情.我把这个service做的工作定位在以下内容
1.查询文件大小
2.返回文件内容
3.删除文件

协议的格式如下
请求模式:文件名称
例如
1:new.txt

请求模式见源代码中的宏定义

这次代码也对原来的程序作了一定的修改
从丑陋的代码渐渐修改.
希望在最终程序完成的时候
能够有比较好的代码风格

这个版本中有一个bug
就是sendfile只是调用一次
而实际上如果是较大的文件
需要在判断EPLLOUT之后不停的sendfile
直到EAGAIN遇见accept_fd阻塞为止
这样直至下次EPOLLOUT发生
再从上次暂停的位置继续发送
下一个版本中将会有这个BUG的修正

#include #include #include #include #include #include #include #include #include #include #include #include #include #define HANDLE_INFO 1 #define HANDLE_SEND 2 #define HANDLE_DEL 3 #define HANDLE_CLOSE 4 #define MAX_REQLEN 1024 #define MAX_PROCESS_CONN 3 #define FIN_CHAR 0x00 #define SUCCESS 0 #define ERROR -1 typedef struct event_handle{ int socket_fd; int file_fd; char request[MAX_REQLEN]; int request_len; int ( * handle )( struct event_handle * ev ); int handle_method; } EV,* EH; typedef int ( * EVENT_HANDLE )( struct event_handle * ev ); int create_listen_fd( int port ){ int listen_fd; struct sockaddr_in my_addr; if( ( listen_fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == -1 ){ perror( "create socket error" ); exit( 1 ); } int flag; int olen = sizeof(int); if( setsockopt( listen_fd, SOL_SOCKET, SO_REUSEADDR , (const void *)&flag, olen ) == -1 ){ perror( "setsockopt error" ); } flag = 1; if( setsockopt( listen_fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &flag, olen ) == -1 ){ perror( "setsockopt error" ); } int flags = fcntl( listen_fd, F_GETFL, 0 ); fcntl( listen_fd, F_SETFL, flags|O_NONBLOCK ); my_addr.sin_family = AF_INET; my_addr.sin_port = htons( port ); my_addr.sin_addr.s_addr = INADDR_ANY; bzero( &( my_addr.sin_zero ), 8 ); if( bind( listen_fd, ( struct sockaddr * )&my_addr, sizeof( struct sockaddr_in ) ) == -1 ) { perror( "bind error" ); exit( 1 ); } if( listen( listen_fd, 1 ) == -1 ){ perror( "listen error" ); exit( 1 ); } return listen_fd; } int create_accept_fd( int listen_fd ){ int addr_len = sizeof( struct sockaddr_in ); struct sockaddr_in remote_addr; int accept_fd = accept( listen_fd, ( struct sockaddr * )&remote_addr, &addr_len ); int flags = fcntl( accept_fd, F_GETFL, 0 ); fcntl( accept_fd, F_SETFL, flags|O_NONBLOCK ); return accept_fd; } int fork_process( int process_num ){ int i; int pid=-1; for( i = 0; i < process_num; i++ ){ if( pid != 0 ){ pid = fork(); } } return pid; } int init_evhandle(EH ev,int socket_fd,EVENT_HANDLE handle){ ev->socket_fd = socket_fd; ev->handle = handle; ev->request_len = 0; ev->handle_method = 0; memset( ev->request, 0, 1024 ); } //accept->accept_queue->request->request_queue->output->output_queue //multi process sendfile int parse_request(EH ev){ ev->request_len--; *( ev->request + ev->request_len - 1 ) = 0x00; int i; for( i=0; irequest_len; i++ ){ if( ev->request[i] == ':' ){ ev->request_len = ev->request_len-i-1; char temp[MAX_REQLEN]; memcpy( temp, ev->request, i ); ev->handle_method = atoi( temp ); memcpy( temp, ev->request+i+1, ev->request_len ); memcpy( ev->request, temp, ev->request_len ); break; } } handle_request( ev ); return SUCCESS; } int handle_request(EH ev){ struct stat file_info; switch( ev->handle_method ){ case HANDLE_INFO: ev->file_fd = open( ev->request, O_RDONLY ); if( ev->file_fd == -1 ){ send( ev->socket_fd, "open file failed\n", strlen("open file failed\n"), 0 ); return -1; } fstat(ev->file_fd, &file_info); char info[MAX_REQLEN]; sprintf(info,"file len:%d\n",file_info.st_size); send( ev->socket_fd, info, strlen( info ), 0 ); break; case HANDLE_SEND: ev->file_fd = open( ev->request, O_RDONLY ); if( ev->file_fd == -1 ){ send( ev->socket_fd, "open file failed\n", strlen("open file failed\n"), 0 ); return -1; } fstat(ev->file_fd, &file_info); sendfile( ev->socket_fd, ev->file_fd, 0, file_info.st_size ); break; case HANDLE_DEL: break; case HANDLE_CLOSE: break; } finish_request( ev ); return SUCCESS; } int finish_request(EH ev){ close(ev->socket_fd); close(ev->file_fd); ev->handle_method = -1; clean_request( ev ); return SUCCESS; } int clean_request(EH ev){ memset( ev->request, 0, MAX_REQLEN ); ev->request_len = 0; } int handle_hook_v2( EH ev ){ char in_buf[MAX_REQLEN]; memset( in_buf, 0, MAX_REQLEN ); int recv_num = recv( ev->socket_fd, &in_buf, MAX_REQLEN, 0 ); if( recv_num ==0 ){ close( ev->socket_fd ); return ERROR; } else{ //check ifoverflow if( ev->request_len > MAX_REQLEN-recv_num ){ close( ev->socket_fd ); clean_request( ev ); } memcpy( ev->request + ev->request_len, in_buf, recv_num ); ev->request_len += recv_num; if( recv_num == 2 && ( !memcmp( &in_buf[recv_num-2], "\r\n", 2 ) ) ){ parse_request(ev); } } return recv_num; } int main(){ int listen_fd = create_listen_fd( 3389 ); int pid = fork_process( 3 ); if( pid == 0 ){ int accept_handles = 0; struct epoll_event ev, events[20]; int epfd = epoll_create( 256 ); int ev_s = 0; ev.data.fd = listen_fd; ev.events = EPOLLIN|EPOLLET; epoll_ctl( epfd, EPOLL_CTL_ADD, listen_fd, &ev ); struct event_handle ev_handles[256]; for( ;; ){ ev_s = epoll_wait( epfd, events, 20, 500 ); int i = 0; for( i = 0; ihandle; EH current_event = ( EH )( events[i].data.ptr ); if( ( *current_handle )( current_event ) == 0 ){ accept_handles--; } } else if( events[i].events&EPOLLOUT ){ //need add write event process } } } } else{ //manager the process int child_process_status; wait( &child_process_status ); } return SUCCESS; }

Last modification:November 26th, 2018 at 04:16 pm
If you think my article is useful to you, please feel free to appreciate

Leave a Comment