libevent tcp 简单通信 (二)
客户端
#pragma once
#include <event2/util.h>
class libevent_client
{
public:
libevent_client();
~libevent_client();
void initial(int port);
void connect_communicate();
private:
struct sockaddr_in m_sin;
int m_port;
evutil_socket_t m_fd;
struct event_base *m_base;
struct bufferevent *m_bev;
struct event *m_event;
private:
static void read_cb(struct bufferevent *bev, void *arg);
static void write_cb(struct bufferevent *bev, void *arg);
static void event_cb(struct bufferevent *bev, short events, void *arg);
static void input_cb(evutil_socket_t fd, short events, void *arg);
static int i;
};
#include "libevent_client.h"
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/event.h>
libevent_client::libevent_client()
{
}
libevent_client::~libevent_client()
{
}
void libevent_client::initial(int port)
{
m_port = port;
memset(&m_sin, 0, sizeof(m_sin));
m_sin.sin_family = AF_INET;
m_sin.sin_port = htons(m_port);
//m_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
inet_pton(AF_INET, "192.168.5.115", &m_sin.sin_addr.s_addr);
#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
// 创建base
m_base = event_base_new();
// 将套接字和base关联起来,得到bufferevent
m_bev = bufferevent_socket_new(m_base, -1, BEV_OPT_CLOSE_ON_FREE);
if (!m_bev)
{
std::cout << "error , create socket buffer." << std::endl;
return;
}
}
void libevent_client::read_cb(struct bufferevent *bev, void *arg)
{
char buf[1024] = { 0 };
//直接从bufferevent将数据读取出来
bufferevent_read(bev, buf, sizeof(buf));
int length = strlen(buf);
if (length)
{
std::cout << "client recv msg:" << buf << std::endl;
}
// // 从bufferevent将数据读取出来,存放到evbuffer中
//struct evbuffer *input = bufferevent_get_input(bev);
//int length = evbuffer_get_length(input);
//if (length)
//{
// evbuffer_remove(input, buf, sizeof(buf));
// std::cout << "client recv msg:" << buf << std::endl;
//}
memset(buf, 0, 1024);
return;
}
void libevent_client::write_cb(struct bufferevent *bev, void *arg)
{
//// listen client send message. if client not send message will not trigger this callback
//// if send message not use evbuffer, then bufferevent_get_input can not get the message
//char buf[1024] = { 0 };
//struct evbuffer *output = bufferevent_get_output(bev);
//int length = evbuffer_get_length(output);
//if (length)
//{
// evbuffer_remove(output, buf, sizeof(buf));
// std::cout << "client send msg:" << buf << std::endl;
//}
//memset(buf, 0, 1024);
return;
}
void libevent_client::event_cb(struct bufferevent *bev, short events, void *arg)
{
if (events & BEV_EVENT_EOF)
{
std::cout << "Connection closed." << std::endl;
bufferevent_free(bev);
}
else if (events & BEV_EVENT_ERROR)
{
std::cout << "Got an error on the connection." << std::endl;
bufferevent_free(bev);
}
else if (events & BEV_EVENT_CONNECTED)
{
std::cout << "Connection server success." << std::endl;
}
return;
}
void libevent_client::input_cb(evutil_socket_t fd, short events, void *arg)
{
// 输入事件加入到未决事件集中后,激活了input_cb,此时event_cb还未被激活
bufferevent *bev = (bufferevent *)arg;
char buf[1024] = { 0 };
if (i > 0 && i < 10)
{
//std::cout << "input the message send to server: ";
//std::cin >> buf;
memcpy(buf, itoa(i, buf, _MAX_ITOSTR_BASE10_COUNT), 1);
}
if (strlen(buf))
{
bufferevent_write(bev, buf, strlen(buf) + 1);
}
memset(buf, 0, 1024);
Sleep(1000);
i++;
return;
}
void libevent_client::connect_communicate()
{
// 连接服务端
int res = bufferevent_socket_connect(m_bev, (struct sockaddr *)&m_sin, sizeof(m_sin));
if (res != 0)
{
std::cout << "connect failed." << std::endl;
return;
}
bufferevent_setcb(m_bev, read_cb, write_cb, event_cb, NULL);
bufferevent_enable(m_bev, EV_READ | EV_PERSIST);
m_event = event_new(m_base, bufferevent_getfd(m_bev), EV_WRITE | EV_PERSIST, input_cb, m_bev);
event_add(m_event, NULL);
int i = event_base_get_num_events(m_base, EVENT_BASE_COUNT_ADDED);
event_base_dispatch(m_base);
event_base_free(m_base);
event_free(m_event);
return;
}
测试
#include <iostream>
#include "libevent_client.h"
int libevent_client::i = 0;
int main()
{
libevent_client client;
client.initial(6000);
client.connect_communicate();
}
服务端
#pragma once
#include <event2/util.h>
class libevent_server
{
public:
libevent_server();
~libevent_server();
void initial(int port);
void creat_bind_accept();
private:
struct sockaddr_in m_sin;
int m_port;
struct event_base *m_base;
struct evconnlistener *m_listener;
private:
static void conn_readcb(struct bufferevent *bev, void *user_data);
static void conn_writecb(struct bufferevent *bev, void *user_data);
static void conn_eventcb(struct bufferevent *bev, short events, void *user_data);
static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data);
};
#include "libevent_server.h"
#include <iostream>
#include <event2/bufferevent.h>
#include <event2/buffer.h>
#include <event2/listener.h>
#include <event2/event.h>
libevent_server::libevent_server()
{
}
libevent_server::~libevent_server()
{
}
void libevent_server::conn_readcb(struct bufferevent *bev, void *user_data)
{
char buf[1024] = { 0 };
//// 直接将数据从bufferevent中读取出来
//bufferevent_read(bev, buf, sizeof(buf));
//int length = strlen(buf);
//if (length)
//{
// std::cout << "server recv msg:" << buf << std::endl;
//}
// 将数据从bufferevent存放到evbuffer中
struct evbuffer *input = bufferevent_get_input(bev);
int length = evbuffer_get_length(input);
if (length)
{
evbuffer_remove(input, buf, sizeof(buf));
std::cout << "server recv msg:" << buf << std::endl;
bufferevent_getfd(bev);
bufferevent_write(bev, buf, strlen(buf) + 1);
}
memset(buf, 0, 1024);
return;
}
void libevent_server::conn_writecb(struct bufferevent *bev, void *user_data)
{
// listen server send message. if server not send message will not trigger this callback
// if send message not use evbuffer, then bufferevent_get_input can not get the message
char buf[1024] = { 0 };
struct evbuffer *output = bufferevent_get_output(bev);
int length = evbuffer_get_length(output);
if (length)
{
evbuffer_copyout(output, buf, sizeof(buf));
std::cout << "server send msg:" << buf << std::endl;
}
evbuffer_free(output);
memset(buf, 0, 1024);
return;
}
void libevent_server::conn_eventcb(struct bufferevent *bev, short events, void *user_data)
{
if (events & BEV_EVENT_EOF)
{
std::cout << "Connection closed." << std::endl;
}
else if (events & BEV_EVENT_ERROR)
{
std::cout << "Got an error on the connection." << std::endl;
}
/* None of the other events can happen here, since we haven't enabled timeouts */
bufferevent_free(bev);
return;
}
void libevent_server::listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data)
{
struct event_base *base = (struct event_base *)user_data;
struct bufferevent *bev;
bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
if (!bev)
{
std::cout << "Error constructing bufferevent!" << std::endl;
event_base_loopbreak(base);
return;
}
bufferevent_setcb(bev, conn_readcb, NULL, conn_eventcb, NULL);
bufferevent_enable(bev, EV_READ | EV_WRITE);
return;
}
void libevent_server::initial(int port)
{
m_port = port;
m_sin = { 0 };
m_sin.sin_family = AF_INET;
m_sin.sin_port = htons(m_port);
#ifdef _WIN32
WSADATA wsa_data;
WSAStartup(0x0201, &wsa_data);
#endif
m_base = event_base_new();
if (!m_base)
{
std::cout << "not initial libevent." << std::endl;
return;
}
return;
}
void libevent_server::creat_bind_accept()
{
// 绑定
m_listener = evconnlistener_new_bind(m_base, listener_cb, (void *)m_base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, -1,
(struct sockaddr*)&m_sin, sizeof(m_sin));
// 启动循环监听
event_base_dispatch(m_base);
// 释放
evconnlistener_free(m_listener);
event_base_free(m_base);
return;
}
测试
#include <iostream>
#include <string>
#include "libevent_server.h"
int main()
{
libevent_server server;
server.initial(6000);
server.creat_bind_accept();
}
测试结果


浙公网安备 33010602011771号