09libevent library server and client TCP communication process and code examples

09libevent library server and client TCP communication process and code examples

以下是关于libevent学习的相关文章:
01 Download and installation of the libevent library and test whether the installation is successful
02 The overall framework idea of ​​the libevent library
03 The main function of
communication
under the
libevent Area features introduction
07libevent library related functions of the bufferevent event
08libevent library communication server and client main functions
09libevent library server and client TCP communication process and code examples

1 The main process of the server

1 创建event_base()
2 创建服务器连接监听器evconnlistener_new_bind()
3 新连接到来,开始通信:
   //1) 先添加bufferevent事件
   //2) 给bufferevent缓冲区设置三种回调
   //3) 启动bufferevent的读监听(因为bufferevent读监听事件是禁用的)
4 创建event普通事件
5 添加事件到base
6 循环监听事件==>epoll_wait+while(1)
7 释放相关资源

2 Client main process

1 创建event_base()
2 使用bufferevent_socket_new()创建一个用跟服务器通信的bufferevent事件对象
3 使用bufferevent_socket_connect()连接服务器
4 使用bufferevent_setcb()给bufferevent对象的读、写、异常设置回调
5 设置bufferevent对象的读写缓冲区enable、diasble
6 接收、发送数据bufferevent_read()bufferevent_write()
7 释放资源

3 server code

//server.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/listener.h>
#include <event2/bufferevent.h>

void send_cb(evutil_socket_t fd, short what, void *arg); 

// 读缓冲区回调
void read_cb(struct bufferevent *bev, void *arg)
{
    
    
    char buf[1024] = {
    
    0};   
    bufferevent_read(bev, buf, sizeof(buf));
    char* p = "我已经收到了你发送的数据!";
    printf("client say: %s\n", buf);
 
}
 
// 写缓冲区回调
void write_cb(struct bufferevent *bev, void *arg)
{
    
    
    printf("我是写缓冲区的回调函数...您已发送\n"); 
}
 
// 事件
void event_cb(struct bufferevent *bev, short events, void *arg)
{
    
    
    if (events & BEV_EVENT_EOF)
    {
    
    
        printf("connection closed\n");  
    }
    else if(events & BEV_EVENT_ERROR)   
    {
    
    
        printf("some other error\n");
    }
    
    //每次发生异常时都要是否buffevent
    bufferevent_free(bev);    
    printf("buffevent 资源已经被释放...\n"); 
}
 
void cb_listener(
        struct evconnlistener *listener, 
        evutil_socket_t fd, 
        struct sockaddr *addr, 
        int len, void *ptr)
{
    
    
   printf("connect new client\n");
 
   struct event_base* base = (struct event_base*)ptr;
   
   //3 新连接到来,开始通信
   //1) 先添加bufferevent事件
   struct bufferevent *bev;
   bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
 
   //2) 给bufferevent缓冲区设置三种回调
   bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
   //3) 启动bufferevent的读监听(因为bufferevent读监听事件是禁用的)
   bufferevent_enable(bev, EV_READ);
   
    //4 创建event普通事件(参2为int型句柄,需与FILE*类型的stdin区分)
    struct event* ev = event_new(base, STDIN_FILENO, 
                                 EV_READ | EV_PERSIST, 
                                 send_cb, bev);

	//5 添加事件到base
	event_add(ev, NULL);
   
}

void send_cb(evutil_socket_t fd, short what, void *arg)
{
    
    
    char buf[1024] = {
    
    0}; 
    struct bufferevent* bev = (struct bufferevent*)arg;
 //   printf("请输入要发送的数据: \n");
    read(fd, buf, sizeof(buf));
    bufferevent_write(bev, buf, strlen(buf)+1);
}
 
int main(int argc, const char* argv[])
{
    
    
    // init server 
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(9876);
    serv.sin_addr.s_addr = htonl(INADDR_ANY);
 
 	//1 创建base
    struct event_base* base;
    base = event_base_new();

	//2 创建listener(相当于socket,bind,listen,accept),并设置监听回调
    struct evconnlistener* listener;
    listener = evconnlistener_new_bind(base, cb_listener, base, LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE, 36, (struct sockaddr*)&serv, sizeof(serv));//参4代表端口复用并且关闭bufferevent时释放底层端口和套接字,36为listen的监听数
	
	//6 循环监听事件==>epoll_wait+while(1)
    event_base_dispatch(base);
 
 	//7 释放相关资源
    evconnlistener_free(listener);
    event_base_free(base);
 
    return 0;
}

4 Client code

//client.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <event2/event.h>
#include <event2/bufferevent.h>
 
 
void read_cb(struct bufferevent *bev, void *arg)
{
    
    
    char buf[1024] = {
    
    0}; 
    bufferevent_read(bev, buf, sizeof(buf));
    printf("Server say: %s\n", buf);
}
 
void write_cb(struct bufferevent *bev, void *arg)
{
    
    
   printf("我是写缓冲区的回调函数...您已发送\n"); 
}
 
void event_cb(struct bufferevent *bev, short events, void *arg)
{
    
    
    if (events & BEV_EVENT_EOF)
    {
    
    
        printf("connection closed\n");  
    }
    else if(events & BEV_EVENT_ERROR)   
    {
    
    
        printf("some other error\n");
    }
    else if(events & BEV_EVENT_CONNECTED)
    {
    
    
        printf("服务器已连接\n");
        return;
    }
    
    bufferevent_free(bev);
    printf("free bufferevent...\n");
}
 
void send_cb(evutil_socket_t fd, short what, void *arg)
{
    
    
    char buf[1024] = {
    
    0}; 
    struct bufferevent* bev = (struct bufferevent*)arg;
   // printf("请输入要发送的数据: \n");
    read(fd, buf, sizeof(buf));
    bufferevent_write(bev, buf, strlen(buf)+1);
}
 
 
int main(int argc, const char* argv[])
{
    
    
    struct event_base* base;
    base = event_base_new();
 
    struct bufferevent* bev;
    bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
 
    // 连接服务器
    struct sockaddr_in serv;
    memset(&serv, 0, sizeof(serv));
    serv.sin_family = AF_INET;
    serv.sin_port = htons(9876);
    evutil_inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr.s_addr);
    bufferevent_socket_connect(bev, (struct sockaddr*)&serv, sizeof(serv));
 
    // 设置回调
    bufferevent_setcb(bev, read_cb, write_cb, event_cb, NULL);
    bufferevent_enable(bev, EV_READ | EV_PERSIST);
 
    // 创建一个事件
    struct event* ev = event_new(base, STDIN_FILENO, EV_READ | EV_PERSIST,  send_cb, bev);
    
    //添加一个事件
    event_add(ev, NULL);
    
    //循环监听事件==>epoll_wait+while(1)
    event_base_dispatch(base);
 
    event_base_free(base);
 
    return 0;
}

Guess you like

Origin blog.csdn.net/weixin_44517656/article/details/108782652