09libevent库服务端与客户端的TCP通信流程和代码示例

09libevent库服务端与客户端的TCP通信流程和代码示例

以下是关于libevent学习的相关文章:
01libevent库的下载与安装并且测试是否安装成功
02libevent库的整体框架思想
03libevent下通信的主要函数
04libevent库下fifo作为通信的套接字
05libevent库下未决与非未决的解释
06libevent下通信中bufferevent缓冲区的特性介绍
07libevent库下bufferevent事件的相关函数
08libevent库下通信服务端与客户端的主要函数
09libevent库服务端与客户端的TCP通信流程和代码示例

1 服务端主要流程

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 客户端主要流程

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.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.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;
}

猜你喜欢

转载自blog.csdn.net/weixin_44517656/article/details/108782652
今日推荐