#include #include #include #include #include #ifdef _WIN32 #include #else #include #include #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; }