1、libevent相关文章查看文章bufferevent2009-11-09 17:08bufferevent 和 evbuffer 互相配合,就实现了非常好用的带缓冲的 IO。 它在非阻塞 IO 网络编程中非常有用。举个例子,给定一个非阻塞的网络文件描述符 fd,我们想向其中写入很长的一段数据,由于是非阻塞的,我们无法通过一个 while 循环,将所有的数据写到 fd。这时我们可以使用 bufferevent,如下 把数据拷贝到一个 evbuffer 中。 让 bufferevent 监听 fd。 一旦 fd 可写,调用 n = write (fd, .) 往 fd 中写一定的数据, writ
2、e() 返回真正写的数量。 把写了的数据从 evbuffer 中移去。 bufferevent 的实现细节见 libevent-bufferevent-detail。下面给出 evbuffer 的定义和 evbuffer_add() evbuffer_drain() 函数。这些代码加上右边的图例,我们不难理解 evbuffer 的工作原理,不再赘述细节。需要注意的地方为 void (*cb) (), 该指针如果不为 NULL, 那么每当缓冲区有变化,对应的回调函数就会被调用。 evbuffer 可以被用作读缓冲,也可以被用作写缓冲,但是一个 evbuffer 不能既作读缓冲也作写缓冲。 evb
3、uffer 图例struct evbuffer u_char *buffer; u_char *orig_buffer; size_t misalign; size_t totallen; size_t off; void (*cb)(struct evbuffer *, size_t, size_t, void *); void *cbarg; intevbuffer_add(struct evbuffer *buf, const void *data, size_t datlen) size_t need = buf-misalign + buf-off + datlen; size_t
4、oldoff = buf-off; if (buf-totallen buffer + buf-off, data, datlen); buf-off += datlen; /* Tell someone about changes in this buffer */ if (datlen & buf-cb != NULL) (*buf-cb)(buf, oldoff, buf-off, buf-cbarg); return (0); void evbuffer_drain(struct evbuffer *buf, size_t len) size_t oldoff = buf-off; i
5、f (len = buf-off) buf-off = 0; buf-buffer = buf-orig_buffer; buf-misalign = 0; goto done; buf-buffer += len; buf-misalign += len; buf-off -= len; done: /* Tell someone about changes in this buffer */ if (buf-off != oldoff & buf-cb != NULL) (*buf-cb)(buf, oldoff, buf-off, buf-cbarg); evbuffer 还提供其他一些
6、非常好用的接口,列举如下 往 buffer 中格式化输出 int evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap);int evbuffer_add_printf(struct evbuffer *buf, const char *fmt, .) 从 buffer 中读出 int evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen);char *evbuffer_readline(struct evbuffer *buffer
7、);此外,下面的两个函数分别让 buffer 从一个文件描述符中读取数据和写入数据int evbuffer_read(struct evbuffer *buf, int fd, int howmuch);int evbuffer_write(struct evbuffer *buffer, int fd);Parts of libevent which we use These are the parts of the libevent API which we actually use, and would need replacing if we decided to ditch libe
8、vent:#ifndef _EVENT_H_#define _EVENT_H_#ifdef _cplusplusextern C #endif#define EV_TIMEOUT 0x01#define EV_READ 0x02#define EV_WRITE 0x04#define EV_SIGNAL 0x08#define EV_PERSIST 0x10 /* Persistant event */struct event_base;struct event /* . */;void *event_init(void);int event_base_set(struct event_bas
9、e *, struct event *);int event_base_loop(struct event_base *, int);#define evtimer_add(ev, tv) event_add(ev, tv)#define evtimer_set(ev, cb, arg) event_set(ev, -1, 0, cb, arg)#define evtimer_del(ev) event_del(ev)#define signal_add(ev, tv) event_add(ev, tv)#define signal_set(ev, x, cb, arg) event_set(
10、ev, x, EV_SIGNAL|EV_PERSIST, cb, arg)void event_set(struct event *, int, short, void (*)(int, short, void *), void *);int event_add(struct event *, struct timeval *);int event_del(struct event *);struct evbuffer;char *evbuffer_readline(struct evbuffer *);int evbuffer_add(struct evbuffer *, void *, s
11、ize_t);int evbuffer_add_printf(struct evbuffer *, const char *fmt, .);struct bufferevent struct evbuffer *input; struct evbuffer *output; /* . */;typedef void (*evbuffercb)(struct bufferevent *, void *);typedef void (*everrorcb)(struct bufferevent *, short what, void *);struct bufferevent *buffereve
12、nt_new(int fd, evbuffercb readcb, evbuffercb writecb, everrorcb errorcb, void *cbarg);int bufferevent_base_set(struct event_base *base, struct bufferevent *bufev);int bufferevent_enable(struct bufferevent *bufev, short event);int bufferevent_disable(struct bufferevent *bufev, short event);#ifdef _cp
13、lusplus#endif#endif /* _EVENT_H_ */libevent实现telnet代理服务器(2009-09-15 16:17:54) 转载标签: 杂谈/=/ Name : libevent_socket.cpp/ Author : mengchaoming/ Version :/ Copyright : beijing tass/ Description : Hello World in C+, Ansi-style/=#include #include #include #include #include #include #include #include #incl
14、ude #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std;#define SERVER_PORT 3333#define REAL_SERV_PORT 23#define BUFLEN 1024typedef struct int fd_server; int fd_client; struct bufferevent *buf_ev_server; struct buff
15、erevent *buf_ev_client; porxy_server;int GetConnectSocket(char* pServerAddr, int pServerPort) int m_Socket = 0; struct sockaddr_in dest_addr; /创建发送套接字 m_Socket = socket(AF_INET, SOCK_STREAM, 0); if(m_Socket = 0) /失败 return -1; /连接客户计算机 bzero(&dest_addr, sizeof(dest_addr); dest_addr.sin_family = AF_I
16、NET; dest_addr.sin_port = htons(REAL_SERV_PORT); if(inet_aton(192.168.5.123, &dest_addr.sin_addr) 0) printf( 192.168.5.123 is not a valid IPaddressn); exit(1); if(connect(m_Socket, (struct sockaddr *) &dest_addr, sizeof(dest_addr) = -1) perror(connect error!n); exit(1); /连接成功 return m_Socket;int set
17、nonblock(int fd) int flags; flags = fcntl(fd, F_GETFL); if(flags 0) return flags; flags |= O_NONBLOCK; if(fcntl(fd, F_SETFL, flags) input-off = 0) printf(Client disconnected.n); /close(client-fd_server); bufferevent_free(client-buf_ev_client); bufferevent_free(client-buf_ev_server); free(client); re
18、turn; else if(bev-input-off fd_server); bufferevent_free(client-buf_ev_client); bufferevent_free(client-buf_ev_server); free(client); return; bufferevent_enable(client-buf_ev_server, EV_WRITE);void on_write_server(struct bufferevent *bev, void *arg)/作为服务器写事件 porxy_server *client = (porxy_server *) a
19、rg; evbuffer_write(bev-input, client-fd_client); /bufferevent_write_buffer(client-buf_ev_client, bev-input);void on_read_client(struct bufferevent *bev, void *arg) /作为客户端读事件 porxy_server *client = (porxy_server *) arg; if(bev-input-off = 0) printf(Client disconnected.n); /close(client-fd_server); bu
20、fferevent_free(client-buf_ev_server); bufferevent_free(client-buf_ev_client); free(client); return; else if(bev-input-off fd_server); bufferevent_free(client-buf_ev_server); bufferevent_free(client-buf_ev_client); free(client); return; bufferevent_enable(client-buf_ev_client, EV_WRITE);void on_write
21、_client(struct bufferevent *bev, void *arg) /作为客户端写事件 porxy_server *client = (porxy_server *) arg; evbuffer_write(bev-input, client-fd_server); / bufferevent_write_buffer(client-buf_ev_server, bev-input);void on_error(struct bufferevent *bev, short what, void *arg) porxy_server *client = (porxy_serv
22、er *) arg; if(what & EVBUFFER_EOF) printf(Client disconnected.n); else printf(Client socket error, disconnecting.n); close(client-fd_server); close(client-fd_client);void on_accept(int fd, short ev, void *arg) struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr); porxy_server *
23、client = (porxy_server *) calloc(1, sizeof(porxy_server); if(client = NULL) printf(malloc failedn); return; client-fd_server = accept(fd, (struct sockaddr *) &client_addr, &client_len); if(client-fd_server = -1) warn( failed); return; if(setnonblock(client-fd_server) buf_ev_server = bufferevent_new(
24、client-fd_server, on_read_server, on_write_server, on_error, client); client-fd_client = GetConnectSocket(192.168.5.123, 23); client-buf_ev_client = bufferevent_new(client-fd_client, on_read_client, on_write_client, on_error, client); if(setnonblock(client-fd_client) buf_ev_client, EV_READ); /bufferevent_enable(client-buf_ev_client, EV_WRITE); bufferevent_enable(client-buf_ev_server, EV_READ); /bufferevent_enable(client-buf_ev_server, EV_WRITE); printf(ed connection from %sn, inet_ntoa(client_addr.sin_addr);int main(int argc, char *argv) int listen_fd; struct sockaddr_in listen_a
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1