首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >tcp 127.0.0.1在同一节点上的进程间通信非常慢

tcp 127.0.0.1在同一节点上的进程间通信非常慢
EN

Ask Ubuntu用户
提问于 2021-01-11 02:55:00
回答 1查看 194关注 0票数 0

在同一主机上Tcp通信非常慢,为127.0.0.1或eth IP(例如:10.10.253.12)。服务器监听0.0.0.0:2000,客户端连接到127.0.0.1:2000或本地eth ip:10.10.253.12:2000,CS传输速度仅为每秒100 ip。C编写的程序使用libevent编写的程序和Java使用Netty编写的程序具有相同的效果,程序编写如下:

  1. 服务器接受连接,回显它恢复的所有内容。
  2. 客户端发送任意128字节的数据,当套接字可写时,再发送128字节的数据;读取并丢弃它恢复的数据。

如果在不同的机器上运行,以每秒30 at的速度运行,这对客户机\服务器程序可以正常工作。

但零q对通信由127.0.0.1没有这样的问题。

服务器端代码是:

代码语言:javascript
运行
复制
---start listener
struct evconnlistener *listener = evconnlistener_new_bind(leader,
    listener_cb, NULL,
    LEV_OPT_REUSEABLE | LEV_OPT_CLOSE_ON_FREE, s_backlog, &addr,
    addrlen);
if (!listener) {
    logit("Could not create a listener!");
    return 1;
}
int fd = evconnlistener_get_fd(listener);
int keepAlive = 0; // 非0值,开启keepalive属性
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));
do{
    if (event_base_loop(leader, EVLOOP_NO_EXIT_ON_EMPTY) < 0){
        break;
    }
}while(!event_base_got_exit(leader));

---connect processing
static void listener_cb(struct evconnlistener *listener, evutil_socket_t fd, struct sockaddr *sa, int socklen, void *user_data) {
    if (s_rcvbufsize > 0){
        setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&s_rcvbufsize, sizeof(s_rcvbufsize));
    }
    if (s_sndbufsize > 0){
        setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&s_sndbufsize, sizeof(s_sndbufsize));
    }
    setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&s_tcpnodelay, sizeof(s_tcpnodelay));
    int keepAlive = 0;    // 非0值,开启keepalive属性
    setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));

    struct bufferevent *bev = bufferevent_socket_new(s_worker, fd, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE);
    if (!bev) {
        logit("Error constructing bufferevent!");
        evutil_closesocket(fd);
        return;
    }
    bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL);
    bufferevent_enable(bev, EV_READ);
}

---read\write processing
static void conn_writecb(struct bufferevent *bev, void *user_data) {
}
static void conn_readcb(struct bufferevent *bev, void *user_data) {
    struct evbuffer *input = bufferevent_get_input(bev);
    int len = evbuffer_get_length(input);

    struct evbuffer *output = bufferevent_get_output(bev);
    evbuffer_add_buffer(output, input);
}

客户端代码是:

代码语言:javascript
运行
复制
---init connection
struct bufferevent* bev= bufferevent_socket_new(s_event_base, -1, BEV_OPT_CLOSE_ON_FREE|BEV_OPT_THREADSAFE);
if (!bev){
    return 1;
}
struct timeval tv;
tv.tv_sec = 30; //connect timeout
tv.tv_usec = 0;
bufferevent_set_timeouts(bev, NULL, &tv);
bufferevent_setcb(bev, NULL, NULL, connect_eventcb, (void*)s_event_base);
int flag = bufferevent_socket_connect(bev, &s_target_sockaddr, s_target_socklen);
if (-1 == flag ){
    bufferevent_free(bev);
    return 1;
}

---connected processing
static void connect_eventcb(struct bufferevent *bev, short events, void *user_data) {
    if (events & (BEV_EVENT_EOF | BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)){
        bufferevent_free(bev);
    }else if (events & BEV_EVENT_CONNECTED) {
        int fd = bufferevent_getfd(bev);
        if (s_sorcvbufsize > 0){
            setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&s_sorcvbufsize, sizeof(s_sorcvbufsize));
        }
        if (s_sosndbufsize > 0){
            setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&s_sosndbufsize, sizeof(s_sosndbufsize));
        }
        setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&s_tcpnodelay, sizeof(s_tcpnodelay));
        int keepAlive = 0;    // 非0值,开启keepalive属性
        setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (void *)&keepAlive, sizeof(keepAlive));

        bufferevent_setwatermark(bev, EV_WRITE, s_snd_wmark_l, s_snd_wmark_h);
        bufferevent_setcb(bev, conn_readcb, conn_writecb, conn_eventcb, NULL);

        bufferevent_enable(bev, EV_READ|EV_WRITE);
        bufferevent_trigger(bev, EV_WRITE, BEV_TRIG_IGNORE_WATERMARKS|BEV_OPT_DEFER_CALLBACKS);
    }
}

---read/write processing
static void conn_writecb(struct bufferevent *bev, void *user_data) {
    struct evbuffer *output = bufferevent_get_output(bev);
    for (int len = evbuffer_get_length(output); len < s_snd_wmark_h; len += s_sendsize){
        if (0 != bufferevent_write(bev, s_send_buf, s_sendsize)){
            break;
        }
    }
}
static void conn_readcb(struct bufferevent *bev, void *user_data) {
    struct evbuffer *input = bufferevent_get_input(bev);
    evbuffer_drain(input, 0x7FFFFFFF);
}

KeepAliveReq捕获显示,无论如何设置SO_KEEPALIVE,都有许多SO_KEEPALIVE:鲨鱼捕获结果1

鲨鱼捕获结果2

EN

回答 1

Ask Ubuntu用户

发布于 2021-01-12 14:43:17

我现在测试并解决了这个问题:主要原因是服务器端的发送缓冲区大小是两个小的(8K),然后是recv大小,这导致了服务器发送的拥塞。

当我将缓冲区大小调整到32K时,问题就消失了。

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

https://askubuntu.com/questions/1306904

复制
相关文章

相似问题

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