#include <iostream>
|
|
#include <event2/event.h>
|
|
#include <string.h>
|
|
#include <thread>
|
|
#include <errno.h>
|
|
|
|
#define SPORT 5001
|
|
#ifdef _WIN32
|
|
|
|
#else
|
|
#include <signal.h>
|
|
#endif // !_WIN32
|
|
|
|
using namespace std;
|
|
//正常断开连接也会进入 超时会进入
|
|
void client_cb(evutil_socket_t s,short w,void *arg){
|
|
//水平触发LT 只要有数据没处理会 一直进入
|
|
//边缘触发ET 有数据时只触发一次
|
|
event *ev = (event *) arg;
|
|
if(w&EV_TIMEOUT){
|
|
cout << "timeout" << endl;
|
|
//需要清理event
|
|
event_free(ev);
|
|
evutil_closesocket(s);
|
|
return;
|
|
}
|
|
|
|
char buf[1024]= {0};
|
|
int len = recv(s,buf,sizeof(buf)-1,0);
|
|
if(len > 0){
|
|
cout << buf << flush;
|
|
send(s,"ok",2,0);
|
|
}
|
|
else{
|
|
//需要清理event
|
|
cout << "event_free" << endl;
|
|
event_free(ev);
|
|
evutil_closesocket(s);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void listen_cb(evutil_socket_t s,short w,void *arg){
|
|
cout << "listen_cb" << endl;
|
|
|
|
sockaddr_in sin;
|
|
socklen_t size = sizeof(sin);
|
|
//读取连接信息
|
|
evutil_socket_t client = accept(s,(sockaddr*)&sin,&size);
|
|
char ip[16] = {0};
|
|
evutil_inet_ntop(AF_INET,&sin.sin_addr,ip,sizeof(ip)-1);
|
|
cout << "client ip is " << ip << endl;
|
|
|
|
//客户端数据读取事件
|
|
event_base *base = (event_base*)arg;
|
|
event *ev = event_new(base,client,EV_READ|EV_PERSIST ,client_cb,event_self_cbarg());
|
|
|
|
timeval t = {10,0};
|
|
|
|
event_add(ev,&t);
|
|
}
|
|
|
|
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();
|
|
|
|
cout << "test event server" << endl;
|
|
|
|
evutil_socket_t sock = socket(AF_INET,SOCK_STREAM,0);
|
|
if(sock == 0){
|
|
cout << "socket error:" << strerror(errno) << endl;
|
|
return -1;
|
|
}
|
|
|
|
//绑定端口地址
|
|
sockaddr_in sin;
|
|
memset(&sin,0,sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons(SPORT);
|
|
int re = ::bind(sock,(sockaddr*)&sin,sizeof(sin));
|
|
if(re != 0){
|
|
cerr << "bind error: " << strerror(errno) << endl;
|
|
return -1;
|
|
}
|
|
|
|
//设置地址复用和非阻塞
|
|
evutil_make_socket_nonblocking(sock);
|
|
evutil_make_listen_socket_reuseable(sock);
|
|
|
|
//开始监听
|
|
listen(sock,10);
|
|
|
|
//开始接收连接事件
|
|
event *ev = event_new(base,sock,EV_READ|EV_PERSIST /* |EV_ET*/ ,listen_cb,base); //默认水平触发
|
|
event_add(ev,0);
|
|
|
|
//进入事件主循环
|
|
event_base_dispatch(base);
|
|
evutil_closesocket(sock);
|
|
event_base_free(base);
|
|
|
|
return 0;
|
|
|
|
}
|