|
|
@ -0,0 +1,114 @@ |
|
|
|
#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; |
|
|
|
|
|
|
|
} |