首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于libevent的回显服务器卡住了

基于libevent的回显服务器卡住了
EN

Stack Overflow用户
提问于 2020-11-27 09:21:46
回答 1查看 104关注 0票数 0

这是一个基于echoServer的libevent,我做了一点调整(非常小)。

问题是,当再次运行客户端模拟时,它似乎被卡住了。客户端是这样做的:它打开一个到这个服务器的TCP连接,发送一个小数据(大约20B)并等待回复,然后它关闭与TCP RST的连接,然后重复。

在几千次(有时约20000次)迭代之后,客户端停止。Wireshark监听环回接口时显示,当它停止时,最后一个TCP会话有从客户端发送的数据,但服务器没有回显/发送回客户端,从而导致客户端挂起。

有什么想法吗?提前感谢!

代码语言:javascript
运行
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include <netinet/tcp.h>
#include <event.h>
#include <event2/listener.h>
#include <event2/bufferevent_ssl.h>

struct event_base *base;

static void echo_read_cb(struct bufferevent *bev, void *ctx) {
    /* This callback is invoked when there is data to read on bev. */
    struct evbuffer *input = bufferevent_get_input(bev);
    struct evbuffer *output = bufferevent_get_output(bev);
    
    /* Copy all the data from the input buffer to the output buffer. */
    int ret = evbuffer_add_buffer(output, input);
    if (ret) {
        printf("error happened when adding buf\n");
    }
}

static void echo_event_cb(struct bufferevent *bev, short events, void *ctx) {
    if (events & (BEV_EVENT_EOF|BEV_EVENT_ERROR)) {
        int fd = bufferevent_getfd(bev);
        evutil_closesocket(fd);
        bufferevent_free(bev);

        return;
    }
}
static void accept_error_cb(struct evconnlistener *listener, void *ctx) {
    struct event_base *base = evconnlistener_get_base(listener);
    int err = EVUTIL_SOCKET_ERROR();
    fprintf(stderr, "Got an error %d (%s) on the listener. "
            "Shutting down.\n", err, evutil_socket_error_to_string(err));
}

static void accept_conn_cb(struct evconnlistener *serv, int sock, struct sockaddr *sa,
             int sa_len, void *arg) {
    struct bufferevent *bev = bufferevent_socket_new(
            base, sock, BEV_OPT_CLOSE_ON_FREE);
    int flag = 1; 
    setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
    bufferevent_setcb(bev, echo_read_cb, NULL, echo_event_cb, NULL);

    bufferevent_enable(bev, EV_READ|EV_WRITE);
}


int main(int argc, char **argv) {
    struct evconnlistener *listener;
    struct sockaddr_in sin;

    memset(&sin, 0, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_port = htons(9999);
    sin.sin_addr.s_addr = htonl(0x7f000001); /* 127.0.0.1 */

    base = event_base_new();
    listener = evconnlistener_new_bind(base, accept_conn_cb, NULL,
            LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1,
            (struct sockaddr*)&sin, sizeof(sin));
    if (!listener) {
            perror("Couldn't create listener");
            return 1;
    }
    evconnlistener_set_error_cb(listener, accept_error_cb);
    event_base_loop(base, 0);

    evconnlistener_free(listener);
    return 0;
}
EN

回答 1

Stack Overflow用户

发布于 2020-11-28 01:20:57

找出问题的原因:在函数echo_event_cb中,有一个调用evutil_closesocket(fd);这不仅是不必要的,而且是有害的!在删除了对close socket的调用后,它可以完美地工作。

这是不必要的,因为bufferedevent是用BEV_OPT_CLOSE_ON_FREE创建的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65031016

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档