#include <iostream>
|
|
#include <event2/event.h>
|
|
#include <event2/thread.h>
|
|
#include <event2/listener.h>
|
|
#include <event2/bufferevent.h>
|
|
|
|
|
|
#ifdef _WIN32
|
|
#include <string>
|
|
#else
|
|
#include <signal.h>
|
|
#include <string.h>
|
|
#endif // !_WIN32
|
|
|
|
using namespace std;
|
|
|
|
static string recvstr = "";
|
|
static int recvCount = 0;
|
|
static int sendCount = 0;
|
|
|
|
void read_cb(bufferevent * bev, void *arg) {
|
|
cout << "[R]" << endl;
|
|
|
|
char data[1024] = { 0 };
|
|
int len = bufferevent_read(bev, data, sizeof(data) - 1);
|
|
if (len <= 0)return;
|
|
recvstr += data;
|
|
recvCount += len;
|
|
|
|
/* if(strstr(data,"quit")!= NULL){
|
|
cout << "quit" << endl;
|
|
bufferevent_free(bev); // BEV_OPT_CLOSE_ON_FREE 设置了这个才会关闭
|
|
} */
|
|
//发送数据 写入到输出缓冲
|
|
bufferevent_write(bev, "ok", 3);
|
|
}
|
|
|
|
void write_cb(bufferevent * bev, void *arg) {
|
|
cout << "[W]" << endl;
|
|
}
|
|
|
|
//错误 超时 连接断开会进入
|
|
void event_cb(struct bufferevent *bev, short what, void *ctx) {
|
|
cout << "[CB]" << endl;
|
|
|
|
//读取超时事件发生后,数据读取停止
|
|
if (what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING) {
|
|
char data[1024] = { 0 };
|
|
int len = bufferevent_read(bev, data, sizeof(data) - 1);
|
|
if (len > 0) {
|
|
recvCount += len;
|
|
recvstr += data;
|
|
}
|
|
cout << "read timeout " << endl;
|
|
|
|
//bufferevent_enable(bev,EV_READ); //可以重新设置
|
|
bufferevent_free(bev);
|
|
cout << recvstr << endl;
|
|
cout << "recvCOunt" << recvCount << " sendCount" << sendCount << endl;
|
|
|
|
}
|
|
else if (what & BEV_EVENT_ERROR) {
|
|
bufferevent_free(bev);
|
|
}
|
|
else {
|
|
cout << "other " << endl;
|
|
}
|
|
}
|
|
|
|
void listen_cb(struct evconnlistener *ev, evutil_socket_t s,
|
|
struct sockaddr *insin, int socklen, void *arg)
|
|
{
|
|
cout << "listen_cb" << endl;
|
|
|
|
struct sockaddr_in *sin = (struct sockaddr_in *)&insin;
|
|
int port = ntohs(sin->sin_port);
|
|
|
|
char ip[16] = { 0 };
|
|
evutil_inet_ntop(AF_INET, &sin->sin_addr, ip, sizeof(ip) - 1);
|
|
cout << "client ip is " << ip << "port is " << port << endl;
|
|
|
|
|
|
event_base* base = (event_base*)arg;
|
|
//创建bufferevent上下文 BEV_OPT_CLOSE_ON_FREE清理bufferevent时关闭socket
|
|
bufferevent * bev = bufferevent_socket_new(base, s, BEV_OPT_CLOSE_ON_FREE);
|
|
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
|
|
|
//设置水位
|
|
//读取水位
|
|
bufferevent_setwatermark(bev, EV_READ,
|
|
10, //低水位0就是无限制 默认0 有10个数据才会回调函数被调用
|
|
10); //高水位0就是无限制 默认0 超过10的数据会拆分成多个10调用多次
|
|
|
|
bufferevent_setwatermark(bev, EV_WRITE,
|
|
5, // 低水位0就是无限制 默认0 缓冲数据低于5 写入回调内调用
|
|
0); //暂时无效
|
|
|
|
timeval t1 = { 0,50000 };
|
|
bufferevent_set_timeouts(bev, &t1, NULL);
|
|
bufferevent_setcb(bev, read_cb, write_cb, event_cb, base);
|
|
}
|
|
|
|
void clinet_read_cb(bufferevent * bev, void *arg) {
|
|
cout << "[clinet R]" << endl;
|
|
char data[1024] = { 0 };
|
|
int len = bufferevent_read(bev, data, sizeof(data) - 1);
|
|
if (len <= 0)return;
|
|
cout << "[" << data << "]" << endl;
|
|
/* if(strstr(data,"quit")!= NULL){
|
|
cout << "quit" << endl;
|
|
bufferevent_free(bev); // BEV_OPT_CLOSE_ON_FREE 设置了这个才会关闭
|
|
} */
|
|
//发送数据 写入到输出缓冲
|
|
//bufferevent_write(bev,"ok",3);
|
|
}
|
|
|
|
void clinet_write_cb(bufferevent * bev, void *arg) {
|
|
cout << "[clinet W]" << endl;
|
|
//激活write
|
|
FILE *fp = (FILE *)arg;
|
|
char data[1024] = { 0 };
|
|
int len = fread(data, 1, sizeof(data) - 1, fp);
|
|
if (len <= 0) {
|
|
// 读到文件结尾或者文件出错
|
|
fclose(fp);
|
|
//立刻清理 可能会造成缓冲数据没有发送结束 !! 不能在这里做
|
|
//bufferevent_free(bev);
|
|
bufferevent_disable(bev, EV_WRITE);
|
|
return;
|
|
}
|
|
sendCount += len;
|
|
bufferevent_write(bev, data, len);
|
|
|
|
}
|
|
|
|
//错误 超时 连接断开会进入
|
|
void clinet_event_cb(struct bufferevent *bev, short what, void *ctx) {
|
|
cout << "[ clinet CB]" << endl;
|
|
|
|
//读取超时事件发生后,数据读取停止
|
|
if (what & BEV_EVENT_TIMEOUT && what & BEV_EVENT_READING) {
|
|
cout << "read timeout " << endl;
|
|
|
|
//bufferevent_enable(bev,EV_READ); //可以重新设置
|
|
bufferevent_free(bev);
|
|
return;
|
|
|
|
}
|
|
else if (what & BEV_EVENT_ERROR) {
|
|
bufferevent_free(bev);
|
|
return;
|
|
}
|
|
|
|
//服务端的关闭事件
|
|
if (what & BEV_EVENT_EOF) {
|
|
cout << "BEV_EVENT_EOF" << endl;
|
|
bufferevent_free(bev);
|
|
}
|
|
|
|
if (what & BEV_EVENT_CONNECTED) {
|
|
cout << "BEV_EVENT_CONNECTED " << endl;
|
|
bufferevent_trigger(bev, EV_WRITE, 0); //触发写事件
|
|
}
|
|
}
|
|
|
|
int main(int agrc, char **agrv)
|
|
{
|
|
|
|
#ifdef _WIN32
|
|
//初始化socket库
|
|
WSADATA wsa;
|
|
WSAStartup(MAKEWORD(2, 2), &wsa);
|
|
#else
|
|
if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
|
|
{ //忽略管道信号,发送数据给已关闭的socket,会飞掉!
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
//创建网络服务器
|
|
event_base *base = event_base_new();
|
|
sockaddr_in sin;
|
|
memset(&sin, 0, sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons(5001);
|
|
|
|
evconnlistener_new_bind(base,
|
|
listen_cb,
|
|
base, LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,
|
|
10,
|
|
(sockaddr *)&sin,
|
|
sizeof(sin));
|
|
|
|
{ //防止变量名重定义
|
|
//调用客户端代码
|
|
// -1 内部创建socket
|
|
bufferevent * bev = bufferevent_socket_new(base, -1, BEV_OPT_CLOSE_ON_FREE);
|
|
sockaddr_in sin;
|
|
memset(&sin, 0, sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons(5001);
|
|
evutil_inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr.s_addr);
|
|
|
|
FILE *fp = fopen("test_buffer_client.cpp", "rb");
|
|
//设置回调函数
|
|
bufferevent_setcb(bev, clinet_read_cb, clinet_write_cb, clinet_event_cb, fp);
|
|
bufferevent_enable(bev, EV_READ | EV_WRITE);
|
|
int ret = bufferevent_socket_connect(bev, (sockaddr*)&sin, sizeof(sin));
|
|
if (ret == 0) {
|
|
cout << "connected" << endl;
|
|
}
|
|
}
|
|
//进入事件主循环
|
|
event_base_dispatch(base);
|
|
event_base_free(base);
|
|
|
|
return 0;
|
|
}
|