#include <netinet/in.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include<iostream>
#include <assert.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define LEN 1024
void do_read(evutil_socket_t fd, short events, void *arg);
void readcb(struct bufferevent *bev, void *ctx)
{
printf("called readcb!\n");
struct evbuffer *input, *output;
std::string recv_buf;
std::string recv_temp;
size_t len;
input = bufferevent_get_input(bev);//其实就是取出bufferevent中的input
output = bufferevent_get_output(bev);//其实就是取出bufferevent中的output
size_t input_len = evbuffer_get_length(input);
printf("input_len: %d\n", input_len);
size_t output_len = evbuffer_get_length(output);
printf("output_len: %d\n", output_len);
ev_ssize_t head_len = evbuffer_copyout(input, (char *)recv_temp.data(),input_len);//copyout
if(head_len == 0)
{
printf("nothing has benn recv.\n");
}
else
{
len = evbuffer_remove(input, (char *)recv_buf.data(), input_len); //move buffer
std::cout<<"recv:"<<recv_buf<<std::endl;
std::string resp = "recv ok,Hello Client\n";
evbuffer_add(output, (char *)resp.data(), resp.size());
}
size_t input_len1 = evbuffer_get_length(input);
printf("input_len1: %d\n", input_len1);
size_t output_len1 = evbuffer_get_length(output);
printf("output_len1: %d\n\n", output_len1);
}
void errorcb(struct bufferevent *bev, short error, void *ctx)
{
if (error & BEV_EVENT_EOF)
{
/* connection has been closed, do any clean up here */
printf("connection closed\n");
}
else if (error & BEV_EVENT_ERROR)
{
/* check errno to see what error occurred */
printf("some other error\n");
}
else if (error & BEV_EVENT_TIMEOUT)
{
/* must be a timeout event handle, handle it */
printf("Timed out\n");
}
bufferevent_free(bev);
}
void do_accept(evutil_socket_t listener, short event, void *arg)
{
struct event_base *base = (event_base *)arg;
struct sockaddr_storage ss;
socklen_t slen = sizeof(ss);
int fd = accept(listener, (struct sockaddr*)&ss, &slen);
if (fd < 0)
{
perror("accept");
}
else if (fd > FD_SETSIZE)
{
close(fd);
}
else
{
struct bufferevent *bev;
evutil_make_socket_nonblocking(fd);
//使用bufferevent_socket_new创建一个struct bufferevent *bev,关联该sockfd,托管给event_base
//BEV_OPT_CLOSE_ON_FREE表示释放bufferevent时关闭底层传输端口。这将关闭底层套接字,释放底层bufferevent等。
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
//设置读写对应的回调函数,三个函数指针分别对应读,写,错误处理。
bufferevent_setcb(bev, readcb, NULL, errorcb, NULL);
//启用读写事件,其实是调用了event_add将相应读写事件加入事件监听队列poll。正如文档所说,如果相应事件不置为true,buf ferevent是不会读写数据的
bufferevent_enable(bev, EV_READ|EV_WRITE);
}
}
void run(void)
{
evutil_socket_t listener;
struct sockaddr_in sin;
struct event_base *base;
struct event *listener_event;
base = event_base_new();
if (!base)
return; /*XXXerr*/
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = 0;
sin.sin_port = htons(8000);
listener = socket(AF_INET, SOCK_STREAM, 0);
evutil_make_socket_nonblocking(listener);
#ifndef WIN32
{
int one = 1;
setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
}
#endif
if (bind(listener, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
perror("bind");
return;
}
if (listen(listener, 16)<0)
{
perror("listen");
return;
}
listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);
/*XXX check it */
event_add(listener_event, NULL);
event_base_dispatch(base);
}
int main(int argc, char **argv)
{
setvbuf(stdout, NULL, _IONBF, 0);
run();
return 0;
}
基于libevent的服务器示例
最新推荐文章于 2024-05-05 17:21:37 发布