使用libevent:echo server
来源:互联网 发布:java编写游戏 编辑:程序博客网 时间:2024/06/05 02:05
原文: https://www.felix021.com/blog/read.php?2068
echo server
// gcc echo_server.c -levent -o es#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <assert.h>#include <event2/event.h>#include <event2/bufferevent.h>#define LISTEN_PORT 9999#define LISTEN_BACKLOG 32void do_accept(evutil_socket_t listener, short event, void *arg);void read_cb(struct bufferevent *bev, void *arg);void error_cb(struct bufferevent *bev, short event, void *arg);void write_cb(struct bufferevent *bev, void *arg);int main(int argc, char *argv[]){ int ret; evutil_socket_t listener; listener = socket(AF_INET, SOCK_STREAM, 0); assert(listener > 0); evutil_make_listen_socket_reuseable(listener); struct sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; sin.sin_port = htons(LISTEN_PORT); if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) < 0) { perror("bind"); return 1; } if (listen(listener, LISTEN_BACKLOG) < 0) { perror("listen"); return 1; } printf ("Listening...\n"); evutil_make_socket_nonblocking(listener); struct event_base *base = event_base_new(); assert(base != NULL); struct event *listen_event; listen_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base); event_add(listen_event, NULL); event_base_dispatch(base); printf("The End."); return 0;}void do_accept(evutil_socket_t listener, short event, void *arg){ struct event_base *base = (struct event_base *)arg; evutil_socket_t fd; struct sockaddr_in sin; socklen_t slen = sizeof(sin); fd = accept(listener, (struct sockaddr *)&sin, &slen); if (fd < 0) { perror("accept"); return; } if (fd > FD_SETSIZE) { //这个if是参考了那个ROT13的例子,貌似是官方的疏漏,从select-based例子里抄过来忘了改 perror("fd > FD_SETSIZE\n"); return; } printf("ACCEPT: fd = %u\n", fd); struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(bev, read_cb, NULL, error_cb, arg); bufferevent_enable(bev, EV_READ|EV_WRITE|EV_PERSIST);}void read_cb(struct bufferevent *bev, void *arg){#define MAX_LINE 256 char line[MAX_LINE+1]; int n; evutil_socket_t fd = bufferevent_getfd(bev); while (n = bufferevent_read(bev, line, MAX_LINE), n > 0) { line[n] = '\0'; printf("fd=%u, read line: %s\n", fd, line); bufferevent_write(bev, line, n); }}void write_cb(struct bufferevent *bev, void *arg) {}void error_cb(struct bufferevent *bev, short event, void *arg){ evutil_socket_t fd = bufferevent_getfd(bev); printf("fd = %u, ", fd); if (event & BEV_EVENT_TIMEOUT) { printf("Timed out\n"); //if bufferevent_set_timeouts() called } else if (event & BEV_EVENT_EOF) { printf("connection closed\n"); } else if (event & BEV_EVENT_ERROR) { printf("some other error\n"); } bufferevent_free(bev);}
简单的压测工具
#include <stdlib.h>#include <stdio.h>#include <assert.h>#include <unistd.h>#include <sys/types.h>#include <sys/epoll.h>#include <fcntl.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>static const char* request = "GET http://localhost/index.html HTTP/1.1\r\nConnection: keep-alive\r\n\r\nxxxxxxxxxxxx";int setnonblocking( int fd ){ int old_option = fcntl( fd, F_GETFL ); int new_option = old_option | O_NONBLOCK; fcntl( fd, F_SETFL, new_option ); return old_option;}void addfd( int epoll_fd, int fd ){ epoll_event event; event.data.fd = fd; event.events = EPOLLOUT | EPOLLET | EPOLLERR; epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &event ); setnonblocking( fd );}bool write_nbytes( int sockfd, const char* buffer, int len ){ int bytes_write = 0; printf( "write out %d bytes to socket %d\n", len, sockfd ); while( 1 ) { bytes_write = send( sockfd, buffer, len, 0 ); if ( bytes_write == -1 ) { return false; } else if ( bytes_write == 0 ) { return false; } len -= bytes_write; buffer = buffer + bytes_write; if ( len <= 0 ) { return true; } } }bool read_once( int sockfd, char* buffer, int len ){ int bytes_read = 0; memset( buffer, '\0', len ); bytes_read = recv( sockfd, buffer, len, 0 ); if ( bytes_read == -1 ) { return false; } else if ( bytes_read == 0 ) { return false; } printf( "read in %d bytes from socket %d with content: %s\n", bytes_read, sockfd, buffer ); return true;}void start_conn( int epoll_fd, int num, const char* ip, int port ){ int ret = 0; struct sockaddr_in address; bzero( &address, sizeof( address ) ); address.sin_family = AF_INET; inet_pton( AF_INET, ip, &address.sin_addr ); address.sin_port = htons( port ); for ( int i = 0; i < num; ++i ) { sleep( 1 ); int sockfd = socket( PF_INET, SOCK_STREAM, 0 ); printf( "create 1 sock\n" ); if( sockfd < 0 ) { continue; } if ( connect( sockfd, ( struct sockaddr* )&address, sizeof( address ) ) == 0 ) { printf( "build connection %d\n", i ); addfd( epoll_fd, sockfd ); } }}void close_conn( int epoll_fd, int sockfd ){ epoll_ctl( epoll_fd, EPOLL_CTL_DEL, sockfd, 0 ); close( sockfd );}int main( int argc, char* argv[] ){ assert( argc == 4 ); int epoll_fd = epoll_create( 100 ); start_conn( epoll_fd, atoi( argv[ 3 ] ), argv[1], atoi( argv[2] ) ); epoll_event events[ 10000 ]; char buffer[ 2048 ]; while ( 1 ) { int fds = epoll_wait( epoll_fd, events, 10000, 2000 ); for ( int i = 0; i < fds; i++ ) { int sockfd = events[i].data.fd; if ( events[i].events & EPOLLIN ) { if ( ! read_once( sockfd, buffer, 2048 ) ) { close_conn( epoll_fd, sockfd ); } struct epoll_event event; event.events = EPOLLOUT | EPOLLET | EPOLLERR; event.data.fd = sockfd; epoll_ctl( epoll_fd, EPOLL_CTL_MOD, sockfd, &event ); } else if( events[i].events & EPOLLOUT ) { if ( ! write_nbytes( sockfd, request, strlen( request ) ) ) { close_conn( epoll_fd, sockfd ); } struct epoll_event event; event.events = EPOLLIN | EPOLLET | EPOLLERR; event.data.fd = sockfd; epoll_ctl( epoll_fd, EPOLL_CTL_MOD, sockfd, &event ); } else if( events[i].events & EPOLLERR ) { close_conn( epoll_fd, sockfd ); } } }}
0 0
- 使用libevent:echo server
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo Server based on libevent
- libevent入门教程:Echo server based on libevent
- libevent入门教程:Echo Server based on libevent
- Libevent:Echo Server Based on libevent
- libevent代码例子---- echo server
- 用libevent多线程方式实现echo server
- libevent for echo server and client
- libevent for echo server and client
- libevent (1) 入门教程:Echo Server based on libevent
- libevent 入门教程:Echo Server based on libevent(转)
- libevent echo服务端程序
- libevent简单echo示例
- vs运行时间的计算
- JavaWeb学习总结(四十九)——简单模拟Sping MVC
- openvz
- MyEclipse下Maven的安装配置
- Java多个版本安装问题
- 使用libevent:echo server
- 【前端性能】必须要掌握的原生JS实现JQuery
- hive的几种文件格式
- 对象的创建:工厂模式/构造函数模式/原型模式 (笔记)
- 禁止手机横竖屏
- JavaWeb学习总结(五十)——文件上传和下载
- linux命令之 ifconfig
- C++ 将“we are happy”中的空格替换成%20,即“we%20are%20happy”
- AndroidImageSlider 滚动图片 viewpager