chat server libevent focus

libevent library based on event-driven (event-driven), high performance; lightweight, focused on the network, using Reactor design model.

libevent network programming process:

server side: all clients via a global data buffer management, read message data management with global message.

 

struct bufferevent* buffers[MAX_CONNECTION];
int cur_con = 0;
int msgs_len = 2;
message_t* msgs;
msgs = (message_t*)malloc(sizeof(message_t)*MAX_MESSAGE_TOTAL)

 

main functions:

struct sockaddr_in srv;
memset(&srv,0,sizeof(srv));
srv.sin_family = AF_INET;
srv.sin_port = htons(10001);
srv.sin_addr.s_addr = htonl(INADDR_ANY);

struct event_base* base;
struct evconnlistener* evlistener;
base = event_base_new();

//evconnlistener_new_bind作用:socket,bind,listen并accept
evlistener
= evconnlistener_new_bind(base,evlistener_cb,args,LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,16,(struct sockaddr *) & SRV, sizeof (SRV)); evconnlistener_set_error_cb (evlistener, evlistener_error_cb); // set evlistener error callback event_base_dispatch ( Base ); // enter event loop

evlistener_error_cb
Callback: When evlistener error occurs, the callback is invoked
void evlistener_error_cb(struct evconnlistener* listener,void *arg){
    print_err("listen errir ,exit");
    event_base_loopbreak(base);
}

evlistener_cb Callback: When evlistener have entered the connection, this callback is invoked. Create a buffer bufferevent_socket_new end dialogue with the customer, the later communication, use of this buffer read and write data.
void evlistener_cb ( struct evconnlistener * evlistener, evutil_socket_t connect_fd, struct sockaddr * cli, int cli_len, void * Arg) 
{ 
    struct bufferevent * Buffer; 
    Buffer = bufferevent_socket_new ( Base , connect_fd, BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS); 
    // create a buffer, and customers side communication 
   bufferevent_enable (buffer, EV_READ
| EV_WRITE); // open the write buffer bufferevent_setcb (buffer, read_cb, NULL, event_cb, arg); // set the buffer callback }

read_cb
Callback: When data buffer, call this callback. bufferevent_read function reads the buffer. bufferevent_write function writes data to the buffer
void read_cb(struct bufferevent* buffer,void* arg){

    message_t* msgs = arg;
    int i = 0;
    while(bufferevent_read(buffer,(msgs + msgs_len),sizeof(message_t)) != 0){
        if(msgs_len == MAX_MESSAGE_TOTAL - 1){
            memcpy(msgs + 2,msgs+(MAX_MESSAGE_TOTAL/2 + 2),sizeof(message_t)*(MAX_MESSAGE_TOTAL/2 - 2));
            msgs_len = (MAX_MESSAGE_TOTAL / 2 - . 1 ); 
        } 
        msgs_len ++ ; 
        the printf ( " Current Message CONT =% D \ n- " , msgs_len);
         for (I = 0 ; I <cur_con; I ++ ) { 
            deliver_msg (buffers [I], (Msgs + msgs_len - . 1 )); 
        // call bufferevent_write in this function () function } } }

event_cb
When the buffer event occurs (error: eof, error), call this callback. Free up resources, and disconnect the client
void event_cb(struct bufferevent* buffer,short event,void* arg){
    int i = 0;
    int n = 0;
    if(event && BEV_EVENT_EOF){
        printf("connection %d closed\n",bufferevent_getfd(buffer));    
    }else if(event && BEV_EVENT_ERROR){
        print_err("got error on thin connection");    
    }
    if(Event && (BEV_EVENT_EOF | BEV_EVENT_ERROR)) {
         for (I = 0 ; I <cur_con; I ++ ) {
             IF (buffers [I] == Buffer) {
                 for (n-= I; n-<cur_con - . 1 ; n-++ ) { 
                    buffers [ n-] = buffers [n-+ . 1 ];     
                }     
                BREAK ;     
            }     
        } 
        cur_con - ; 
        bufferevent_setcb (buffer, NULL, NULL, NULL, NULL); // Turn off all events on the buffer 
        bufferevent_free (buffer); // free buffer , disconnect from the client. 
    } 
}

client side:

main function: to create a base, to create a buffer, and connected to the server, read books on the buffer ancestral event, receiving a user input, the input buffer is written, create a separate thread to run the event-dispatching function.

struct sockaddr_in srv;
memset(&srv,0,sizeof(srv));
srv.sin_port = htons(10001);
srv.sin_family = AF_INET;
inet_pton(AF_INET,argv[1],&srv.sin_addr);

struct event_base* base;
base = event_base_new();
struct bufferevent* buffer;
buffer = bufferevent_socket_new(base,-1,BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
bufferevent_setcb(buffer,read_cb,NULL,NULL,NULL);
bufferevent_enable(buffer, EV_READ | EV_WRITE);

if(pthread_create(&thread_id,NULL,(void*)ev_dispatch,NULL) != 0){
        print_err("create thread failed");    
}
        //处理客户输入
    printf("\033[1;34mplease bind your chat name :\033[0m\n");
    scanf("%s",name);
    memcpy(msg.name,name,sizeof(name));

    printf("\033[1;34minput your message (next) :\033[0m\n");
    while(1){
        //printf("please input your text\n");
        scanf("%s",text);
        memcpy(msg.msg,text,sizeof(text));
        bufferevent_write(buffer,&msg,sizeof(msg)); //将客户消息写入buffer
    }

ev_dispatch
functions: to enter the event loop (receiving a message from the server)
void ev_dispatch(){
    event_base_dispatch(base);
}

read_cb function: When data enters the buffer, the data read cycle. And output to the client terminal.
int read_n = 0;
int cont_ = 1280;
message_t msg_r ;
void
read_cb(struct bufferevent* buffer,void* arg){ //printf("flag \n"); while(1){ //printf("read_n = %d , cont_ = %d \n",read_n,cont_); read_n = bufferevent_read(buffer,((char*)&msg_r) + (1280 - cont_),cont_ ); if(read_n == 0){ break; } //printf("read_n = %d\n",read_n); cont_ = cont_ - read_n; //printf("cont_ = %d\n",cont_); if(cont_ == 0){ printf("\033[31m%s say : ",msg_r.name); printf("%s \033[0m\n",msg_r.msg); cont_ = 1280; read_n = 0; } //printf("read_n = %d ",read_n); } }

Guess you like

Origin www.cnblogs.com/Ccluck-tian/p/12433561.html