Libevent使用範例及代碼說明

利用libevent實現有數據來時,執行ReadBuffer函數,支持多線程。

static EventApiParameter parameter;
memset((void *)&parameter, 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 *)&parameter, 0, sizeof(parameter));
    memcpy((void *)&parameter, 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(&parameter.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 *)&parameter, 0, sizeof(parameter));
    EventApiParameter *p_parameter = ( EventApiParameter *)arg;
    pthread_mutex_lock(&p_parameter->mutex);
    memcpy((void *)&parameter, 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, &parameter.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(&parameter.mutex);
	pthread_create(&thread,NULL,EventHandleThread,(void*)&parameter);
	pthread_detach(thread);
    pthread_cond_wait(&parameter.cond,&parameter.mutex);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章