我承认这篇文章有点标题党,呵呵。其实就是一个能和服务器建立全双工通信的客户端而已,用网络库libevent实现。
从这里也可以看出,同样的功能,分别用epoll和libevent来比较,从代码量和代码清晰度来说,libevent完胜,呵呵。
上代码:
#include <sys/socket.h> #include <string.h> #include <errno.h> #include <stdlib.h> #include <unistd.h> #include <event.h> #include <event2/event.h> //发生了致命错误,输入错误信息,退出程序 void error_quit(const char *str) { perror(str); exit(1); } //连接状态改变时回调的函数 void eventcb(struct bufferevent *bev, short events, void *ptr) { struct event_base *tbase = (struct event_base*)ptr; //如果不是连接成功的消息,就停止事件循环 if ( !(events & BEV_EVENT_CONNECTED) ) { bufferevent_free(bev); event_base_loopbreak(tbase); printf("The connect have been shutdown: %X\n", events); } } //服务器传信息过来了 void sockreadcb(struct bufferevent *bev, void *ptr) { struct evbuffer *input = bufferevent_get_input(bev); evbuffer_write(input, STDOUT_FILENO); } //标准输入传消息过来了 void stdreadcb(struct bufferevent *bev, void *ptr) { struct bufferevent *sockbev = (struct bufferevent*)ptr; struct evbuffer *input = bufferevent_get_input(bev); bufferevent_write_buffer(sockbev, input); } int main(int argc, char **argv) { struct sockaddr_in servaddr; struct event *shellev; int res; struct event_base *base; struct bufferevent *sockbev; struct bufferevent *stdbev; if( argc != 3 ) error_quit("Using: mytelnet <Address> <Port>"); memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons( atoi(argv[2]) ); res = inet_pton(AF_INET, argv[1], &servaddr.sin_addr); if( res != 1 ) error_quit("inet_pton error"); base = event_base_new(); //连接服务器并监听 sockbev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE); res = bufferevent_socket_connect(sockbev, (struct sockaddr *)&servaddr, sizeof(servaddr)); if ( res < 0 ) error_quit("connect error"); bufferevent_setcb(sockbev, sockreadcb, NULL, eventcb, (void*)base); bufferevent_enable(sockbev, EV_READ); bufferevent_enable(sockbev, EV_WRITE); //监听标准输入 stdbev = bufferevent_socket_new(base, STDIN_FILENO, BEV_OPT_CLOSE_ON_FREE); bufferevent_setcb(stdbev, stdreadcb, NULL, NULL, (void*)sockbev); bufferevent_enable(stdbev, EV_READ); bufferevent_enable(stdbev, EV_WRITE); //开始事件循环 event_base_dispatch(base); return 0; }
编译与运行命令: gcc mytelnet.c -o mytelnet -levent ./mytelnet 127.0.0.1 8877
用于测试的服务器:http://blog.csdn.net/aaa20090987/article/details/8769585