利用libevent實現有數據來時,執行ReadBuffer函數,支持多線程。
static EventApiParameter parameter;
memset((void *)¶meter, 0, sizeof(parameter));
parameter.agent_socket.port = port;
//parameter.write_function_point = WriteBuffer;
parameter.read_function_point = ReadBuffer;
parameter.timer=0;
//event和event_base是libevent的兩個基礎結構體
struct event ev;
struct event_base *base;
//申請一個新的event_base
base = event_base_new();
//設置ev,將fd回調函數OnAccept以及回調函數參數arg賦值到ev結構中
//event_set->event_assign
event_set(&ev, fd, EV_READ|EV_PERSIST, OnAccept, (void *)parameter);
//將base賦值到ev結構中,ev->ev_base = base
event_base_set(base, &ev);
//主要作用是將ev結構添加到隊列中
//event_add->event_add_nolock_->event_queue_insert_inserted
event_add(&ev, NULL);
//run forever
//event_dispatch 是程序的主體循環,我們註冊的回調函數就在該循環體中執行
/*event_base_dispatch->event_loop->event_base_loop->event_process_active->event_process_active_single_queue->evcb_callback*/
event_base_dispatch(base);
//never running
//正常情況下不會走到這裏,循環退出時會走到這裏,回收資源
event_del(&ev);
event_base_free(base);
void OnAccept(int fd, short event, void* arg)
{
struct sockaddr_in remote_addr;
EventApiParameter parameter;
memset((void *)¶meter, 0, sizeof(parameter));
memcpy((void *)¶meter, arg, sizeof(parameter));
int sin_size=sizeof(struct sockaddr_in);
int new_fd = accept(fd, (struct sockaddr*) &remote_addr, (socklen_t*)&sin_size);
if(new_fd < 0){
return;
}
//int high;
//evutil_make_listen_socket_reuseable(new_fd);
//evutil_make_socket_nonblocking(new_fd);
//setsockopt(new_fd, SOL_SOCKET, SO_REUSEPORT,
//(const char *)&high, sizeof(int));
memcpy(¶meter.agent_socket.addr, &remote_addr, sizeof(remote_addr));
if (NULL != parameter.accept_function_point)
{
parameter.accept_function_point(remote_addr);
}
parameter.agent_socket.fd = new_fd;
AcceptNewThread(parameter);
}
void* EventHandleThread(void* arg){
//long long_fd = (long)arg;
//int fd = (int)long_fd;
EventApiParameter parameter;
memset((void *)¶meter, 0, sizeof(parameter));
EventApiParameter *p_parameter = ( EventApiParameter *)arg;
pthread_mutex_lock(&p_parameter->mutex);
memcpy((void *)¶meter, p_parameter, sizeof(parameter));
pthread_cond_signal(&p_parameter->cond);
pthread_mutex_unlock(&p_parameter->mutex);
int fd = parameter.agent_socket.fd;
if(fd<0){
return 0;
}
struct event_base *base = event_base_new();
if (NULL == base)
{
return 0;
}
//struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
struct bufferevent *bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (NULL == bev)
{
return 0;
}
//set timer
if (parameter.timer)
{
CreateTimeoutEvent(base, bev);
}
bufferevent_setcb(bev, parameter.read_function_point, NULL, EventError, ¶meter.agent_socket);
bufferevent_enable(bev, EV_READ);
struct timeval write_tv = {1,0};
bufferevent_set_timeouts (bev, NULL, &write_tv);
event_base_dispatch(base);
event_base_free(base);
return 0;
}
void AcceptNewThread(EventApiParameter parameter){
pthread_t thread;
parameter.mutex=PTHREAD_MUTEX_INITIALIZER;
parameter.cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_lock(¶meter.mutex);
pthread_create(&thread,NULL,EventHandleThread,(void*)¶meter);
pthread_detach(thread);
pthread_cond_wait(¶meter.cond,¶meter.mutex);
}