libevent实现echoclient

基于libevent实现了一个简单的echoclient。之前在网上看到的都是echoserver。这里演示一下使用libevent进行客户端编程的基本步骤。

先看代码:

#include "stdafx.h"
#include "event2/event.h"
#include "event2/util.h"

#define ECHO_PORT   8888
#define ECHO_SERVER "127.0.0.1"

struct echo_context{
    struct event_base *base;
    struct event *event_write;
    struct event *event_read;
    const char * echo_contents;
    int echo_contents_len;
    int recved;
};

void write_cb(evutil_socket_t sock, short flags, void * args)
{
    struct echo_context *ec = (struct echo_context *)args; 

    int ret = send(sock, ec->echo_contents, ec->echo_contents_len, 0);
    printf("connected, write to echo server: %d\n", ret);
    event_add(ec->event_read, 0);
}

void read_cb(evutil_socket_t sock, short flags, void * args)
{
    struct echo_context *ec = (struct echo_context *)args; 
    char buf[128];
    int ret = recv(sock, buf, 128, 0);
    
    printf("read_cb, read %d bytes\n", ret);
    if(ret > 0)
    {
        ec->recved += ret;
        buf[ret] = 0;
        printf("recv:%s\n", buf);
    }
    else if(ret == 0)
    {
        printf("read_cb connection closed\n");
        event_base_loopexit(ec->base, NULL);
        return;
    }
    if(ec->recved < ec->echo_contents_len)
    {
        event_add(ec->event_read, 0);
    }
}

static evutil_socket_t make_tcp_socket()
{
    int on = 1;
    evutil_socket_t sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    evutil_make_socket_nonblocking(sock);
#ifdef WIN32
    setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (const char *)&on, sizeof(on));
#else
    setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on, sizeof(on));
#endif

    return sock;
}

static void echo_client(struct event_base *base)
{
    evutil_socket_t sock = make_tcp_socket();
    struct sockaddr_in serverAddr;
    struct event * ev_write = 0;
    struct event * ev_read = 0;
    struct timeval tv={10, 0};
    struct echo_context *ec = (struct echo_context*)calloc(1, sizeof(struct echo_context));
    
    serverAddr.sin_family = AF_INET;
    serverAddr.sin_port = htons(ECHO_PORT);
#ifdef WIN32
    serverAddr.sin_addr.S_un.S_addr = inet_addr(ECHO_SERVER);
#else
    serverAddr.sin_addr.s_addr = inet_addr(ECHO_SERVER);
#endif
    memset(serverAddr.sin_zero, 0x00, 8);

    connect(sock, (struct sockaddr*)&serverAddr, sizeof(serverAddr));

    ev_write = event_new(base, sock, EV_WRITE, write_cb, (void*)ec);
    ev_read = event_new(base, sock, EV_READ , read_cb, (void*)ec);

    ec->event_write = ev_write;
    ec->event_read = ev_read;
    ec->base = base;
    ec->echo_contents = strdup("echo client tneilc ohce\n");
    ec->echo_contents_len = strlen(ec->echo_contents);
    ec->recved = 0;

    event_add(ev_write, &tv);
}

int _tmain(int argc, _TCHAR* argv[])
{
    struct event_base * base = 0;
#ifdef WIN32
    WORD wVersionRequested;
    WSADATA wsaData;

    wVersionRequested = MAKEWORD(2, 2);

    (void) WSAStartup(wVersionRequested, &wsaData);
#endif

    base = event_base_new();
    echo_client(base);
    event_base_dispatch(base);
    event_base_free(base);

	return 0;
}

代码是在windows上实现的。

使用libevent进行客户端编程的基本步骤,在《libevent实现http client》中已经提过,基本如下:

  1. 初始化event_base(后续要运行事件循环)
  2. 创建socket,设置为异步,连接server
  3. 创建写读写事件,先将写事件加入事件循环
  4. 在写事件回调中向server端发送请求并将读事件加入事件循环
  5. 在读事件回调中处理数据,并根据数据是否读取完毕决定是否继续添加读事件
结合本文的示例代码,通过event_base_new()创建event_base,在初始化客户端socket(echo_client)之后,调用event_base_dispatch运行事件循环。

echo_client函数初始化了socket,设置为非阻塞模式,调用connect连接到echoserver,然后添加一个写事件到事件循环中。当连接成功后,会触发写事件。这里将write_cb作为写事件的回调,在调用event_new()时传入。

write_cb()写入一个字符串,然后添加一个读事件,在读事件中读取echoserver的回应。

基本的过程就是这样子了。这是个简单的例子,更复杂的例子,基本流程也是一样的。


要使用libevent实现HTTPS,你需要进行以下步骤: 1. 首先,你需要在编译和安装libevent之前,确保你的系统已经安装了OpenSSL库。OpenSSL提供了HTTPS所需的加密算法和证书管理功能。 2. 下载libevent库的源代码,并解压缩。 3. 在解压缩后的目录中,打开命令行终端,并执行以下命令编译和安装libevent: ``` ./configure make sudo make install ``` 4. 在你的C代码中,添加libevent的头文件: ```c #include <event2/event.h> #include <event2/bufferevent.h> #include <event2/buffer.h> #include <event2/http.h> ``` 5. 初始化libevent库,并创建一个event_base对象: ```c struct event_base *base = event_base_new(); ``` 6. 创建一个SSL_CTX对象,并设置SSL相关的参数,包括证书、私钥等: ```c SSL_CTX *ssl_ctx = SSL_CTX_new(SSLv23_method()); // 设置证书文件和私钥文件路径 SSL_CTX_use_certificate_file(ssl_ctx, "server.crt", SSL_FILETYPE_PEM); SSL_CTX_use_PrivateKey_file(ssl_ctx, "server.key", SSL_FILETYPE_PEM); ``` 7. 创建一个监听socket,并将其绑定到指定的地址和端口上: ```c struct sockaddr_in sin; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(443); evhttp_bind_socket(base, "0.0.0.0", 443); ``` 8. 创建一个evhttp对象,并设置其处理HTTP请求的回调函数: ```c struct evhttp *http = evhttp_new(base); evhttp_set_gencb(http, http_request_callback, NULL); ``` 在回调函数中,你可以处理接收到的HTTPS请求,并返回相应的响应。 9. 开始事件循环,监听和处理HTTPS请求: ```c event_base_dispatch(base); ``` 这样,你就可以使用libevent实现基本的HTTPS服务器。当然,还可以根据具体需求进行更多的定制和扩展。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

foruok

你可以选择打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值