libevent2 简单服务器客户端实现

来源:互联网 发布:微信协议软件 编辑:程序博客网 时间:2024/05/08 20:43

libevent2 简单服务器客户端实现
基本功能,应该比较容易扩展
windows版本,我用的vc编译,linux去掉wsa相关内容,将sprintf_s替换成snprintf应该就可以了。

server.cpp

/*    socket server*/#include <iostream>#include <signal.h>#define WIN32#include <event2/event.h>#include <event2/listener.h>#include <event2/bufferevent.h>#pragma comment(lib,"ws2_32.lib")#pragma comment(lib,"libevent_core.lib")#pragma comment(lib,"libevent_extras.lib")using std::cout;using std::cerr;using std::endl;void p_evconnlistener_cb(struct evconnlistener *, evutil_socket_t, struct sockaddr *, int socklen, void *);void p_bufferevent_read_cb(bufferevent* pBufferEvent, void* pUserData);void p_bufferevent_write_cb(bufferevent* pBufferEvent, void* pUserData);void p_bufferevent_event_cb(bufferevent* pBufferEvent, short what, void* pUserData);void p_sigint_cb(evutil_socket_t fd, short what, void* pUserData);int main(){    cout << "server start" << endl;    // windows网络初始化    WSAData wsaData;    WSAStartup(MAKEWORD(2, 2), &wsaData);    // 初始化eventbase    event_base* pEventBase = event_base_new();    if (pEventBase == NULL)    {        cerr << "event_base fail" << endl;        return 1;    }    // 定制监听地址端口    sockaddr_in server_addr;    size_t server_addr_len = sizeof(sockaddr_in);    memset(&server_addr, 0, server_addr_len);    server_addr.sin_family = AF_INET;    server_addr.sin_addr.s_addr = htonl(ADDR_ANY);    server_addr.sin_port = htons(7777);    // 代替bind&listen方法的方法……    evconnlistener* pEvConnListener = evconnlistener_new_bind(pEventBase,        p_evconnlistener_cb,        pEventBase,        LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE,        -1,        (sockaddr*)&server_addr,        server_addr_len);    // 监听<C-c>中断信号    event* pSigintEvent = evsignal_new(pEventBase, SIGINT, p_sigint_cb, pEventBase);    if ((!pSigintEvent) || (event_add(pSigintEvent, NULL) < 0))    {        cerr << "sigint event fail." << endl;        return 1;    }    // 循环处理消息    event_base_dispatch(pEventBase);    // 清理    evconnlistener_free(pEvConnListener);    event_free(pSigintEvent);    event_base_free(pEventBase);    // windows网络停止    WSACleanup();    cout << "server stop" << endl;    return 0;}// 连接回调void p_evconnlistener_cb(evconnlistener* pEvConnListener, evutil_socket_t fd, sockaddr* addr, int socklen, void* userData){    event_base* pEventBase = (event_base*)userData;    // 绑定连接的socket和bufferevent(这里的socket默认就是非阻塞的)    bufferevent* pBufferEvent = bufferevent_socket_new(pEventBase, fd, BEV_OPT_CLOSE_ON_FREE);    if (!pBufferEvent)    {        cerr << "bufferevent fail." << endl;        event_base_loopbreak(pEventBase);        return;    }    // 添加监听socket,设置回调    bufferevent_setcb(pBufferEvent, p_bufferevent_read_cb, p_bufferevent_write_cb, p_bufferevent_event_cb, NULL);    // 设置处理(监听?)内容:读、写    bufferevent_enable(pBufferEvent, EV_READ | EV_WRITE);}// 数据读取回调void p_bufferevent_read_cb(bufferevent* pBufferEvent, void* pUserData){    // 读数据    char info[255];    size_t infoLen = bufferevent_read(pBufferEvent, info, sizeof(info));    if (infoLen < sizeof(info))        info[infoLen] = 0;    cout << "recv info:" << info << endl;    // 返回数据    char info_ret[255];    sprintf_s(info_ret, sizeof(info_ret), "server ret:%s", info);    bufferevent_write(pBufferEvent, info_ret, strlen(info_ret));}// 写数据回调void p_bufferevent_write_cb(bufferevent* pBufferEvent, void* pUserData){    cout << "react client complete." << endl;}// 事件处理(出错、socket中断)void p_bufferevent_event_cb(bufferevent* pBufferEvent, short what, void* pUserData){    if (what & BEV_EVENT_READING)        cout << "event_cb BEV_EVENT_READING." << endl;    if (what & BEV_EVENT_WRITING)        cout << "event_cb BEV_EVENT_WRITING." << endl;    if (what & BEV_EVENT_EOF)        cout << "event_cb BEV_EVENT_EOF." << endl;    if (what & BEV_EVENT_ERROR)        cout << "event_cb BEV_EVENT_ERROR." << endl;    if (what & BEV_EVENT_TIMEOUT)        cout << "event_cb BEV_EVENT_TIMEOUT." << endl;    if (what & BEV_EVENT_CONNECTED)        cout << "event_cb BEV_EVENT_CONNECTED." << endl;    bufferevent_free(pBufferEvent);}// <C-c>中断信号处理void p_sigint_cb(evutil_socket_t fd, short what, void* pUserData){    event_base* pEventBase = (event_base*)pUserData;    timeval delay = { 2, 0 };    cout << "stop service in 2 seconds." << endl;    event_base_loopexit(pEventBase, &delay);}

client.cpp

/*    libevent临时测试客户端*/#include <iostream>#include <WinSock2.h>#pragma comment(lib,"ws2_32.lib")using std::cout;using std::endl;int main(){    WSAData wsaData;    WSAStartup(MAKEWORD(2, 2), &wsaData);    sockaddr_in addr;    memset(&addr, 0, sizeof(addr));    addr.sin_family = AF_INET;    addr.sin_addr.s_addr = inet_addr("127.0.0.1");    addr.sin_port = htons(7777);    size_t addrLen = sizeof(addr);    SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);    if (sock == INVALID_SOCKET)    {        cout << "create sock error." << WSAGetLastError() << endl;        return 0;    }    if (connect(sock, (const sockaddr*)&addr, addrLen) == SOCKET_ERROR)    {        cout << "connect error." << WSAGetLastError() << endl;        closesocket(sock);        return 0;    }    char info[255];    for (int i = 0; i < 10; ++i)    {        sprintf_s(info, sizeof(info), "client msg:%d", i);        send(sock, info, strlen(info), 0);        memset(info, 0, sizeof(info));        int infoLen = recv(sock, info, sizeof(info), 0);        if (infoLen == 0)        {            cout << "sock closed." << endl;            closesocket(sock);            sock = NULL;            break;        }        else if (infoLen < 0)        {            cout << "recv error." << WSAGetLastError() << endl;            closesocket(sock);            sock = NULL;            break;        }        else        {            cout << "recv info:" << info << endl;        }    }    if (sock)    {        closesocket(sock);        sock = NULL;    }    WSACleanup();    return 0;}
0 0
原创粉丝点击