这是一个基于echoServer的libevent,我做了一点调整(非常小)。
问题是,当再次运行客户端模拟时,它似乎被卡住了。客户端是这样做的:它打开一个到这个服务器的TCP连接,发送一个小数据(大约20B)并等待回复,然后它关闭与TCP RST的连接,然后重复。
在几千次(有时约20000次)迭代之后,客户端停止。Wireshark监听环回接口时显示,当它停止时,最后一个TCP会话有从客户端发送的数据,但服务器没有回显/发送回客户端,从而导致客户端挂起。
有什么想法吗?提前感谢!
#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;
}
发布于 2020-11-28 01:20:57
找出问题的原因:在函数echo_event_cb
中,有一个调用evutil_closesocket(fd)
;这不仅是不必要的,而且是有害的!在删除了对close socket的调用后,它可以完美地工作。
这是不必要的,因为bufferedevent是用BEV_OPT_CLOSE_ON_FREE
创建的。
https://stackoverflow.com/questions/65031016
复制相似问题