我承认这篇文章有点标题党,呵呵。其实就是一个能和服务器建立全双工通信的客户端而已,用网络库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