I/O复用___libevent

版权声明:私藏源代码是违反人性的罪恶行为!博客转载无需告知,学无止境。 https://blog.csdn.net/qq_41822235/article/details/84672483

一、情景再现

典型的C/S模式是这样的,不妨以多线程为例来说明:ser启动一个专门用于处理cli连接请求的线程,一旦需要连接,就accept,与cli建立连接,连接好后将事物交付给其他线程去处理。

当我们从事件监听的角度读看待这个流程的话,服务器端起始有两处需要被监听:1、until有了连接请求才去accept;2、连接建立好了之后,until有了数据传输才会有recv或者send操作。

二、代码实现

2.1 服务器端

#include<iostream>
#include<arpa/inet.h>
#include<sys/socket.h>
#include<event.h>
#include<assert.h>
using namespace std;

void listen_cb(int fd, short event, void* arg); //是否需要accept
void c_cb(int clifd, short event, void *arg); //是否需要recv

int main()
{
    struct event_base *lib = event_base_new(); //初始化libevent

    int fd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != fd);

    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res = bind(fd, (struct sockaddr*)&ser, sizeof(ser));
    assert(-1 != res);

    assert(-1 != listen(fd, 5));

    //创建事件
    struct event* listen_event = event_new(lib, fd, EV_READ|EV_PERSIST, listen_cb, lib);
    assert(NULL != listen_event);

    event_add(listen_event, NULL); //将事件添加到列表中去
    event_base_dispatch(lib); //循环监听
    return 0;
}

//主要是监听是否要accept()
void listen_cb(int fd, short event, void *arg)
{
    struct event_base* lib = (struct event_base*)arg;
    struct sockaddr_in cli;
    socklen_t len = sizeof(cli);
    int clifd = accept(fd, (struct sockaddr*)&cli, &len);
    assert(-1 != clifd);

    //针对是否需要向已连接的客户端提供服务
    struct event* cli_event = event_new(lib, clifd, EV_READ, c_cb, lib);
    assert(NULL != cli_event);

    event_add(cli_event, NULL);
}

//主要是监听是否要recv或者send
void c_cb(int clifd, short event, void *arg)
{
    char buf[128] = {'\0'};
    int n = recv(clifd, buf, 127, 0);//一旦连接好的客户端不再发送数据n=0
    if(n > 0)
    {
        cout<<buf<<endl;
        assert(-1 != send(clifd, "OK", sizeof("OK"), 0));
    }
    else
    {
        close(clifd);
    }
}                        

2.2客户端

#include<iostream>
#include<event.h>
#include<sys/socket.h>
#include<arpa/inet.h> //inet_addr()
#include<assert.h>
using namespace std;


int main()
{
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    assert(-1 != fd);

    struct sockaddr_in ser;
    ser.sin_family = AF_INET;
    ser.sin_port = htons(6000);
    ser.sin_addr.s_addr = inet_addr("127.0.0.1");

    int res= connect(fd, (struct sockaddr*)&ser, sizeof(ser));
    assert(-1 != res);

    assert(-1 != send(fd, "hello", sizeof("hello"), 0));

    char buf[128] = {'\0'};
    int n = recv(fd, buf, 127, 0);
    if(n > 0);
        cout<<buf<<endl;
    
    return 0;
}

2.3运行结果

猜你喜欢

转载自blog.csdn.net/qq_41822235/article/details/84672483