Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

setReuseable sets whether the socket fd is written in reverse. #244

Closed
ddwapple opened this issue Sep 6, 2024 · 6 comments
Closed

setReuseable sets whether the socket fd is written in reverse. #244

ddwapple opened this issue Sep 6, 2024 · 6 comments

Comments

@ddwapple
Copy link

ddwapple commented Sep 6, 2024

SO_REUSEPORT is set in connect.

int SockUtil::connect(const char *host, uint16_t port, bool async, const char *local_ip, uint16_t local_port) {
...
setReuseable(sockfd);
...
}

However, SO_REUSEPORT is unset in listen.

int SockUtil::listen(const uint16_t port, const char *local_ip, int back_log) {
...
setReuseable(fd, true, false);
...
}

I'm a little confused. Clients don't need to use SO_REUSEPORT, right? Only the server needs it. Thanks for the explanation.

在connect中会设置SO_REUSEPORT

int SockUtil::connect(const char *host, uint16_t port, bool async, const char *local_ip, uint16_t local_port) {
...
setReuseable(sockfd);
...
}

在listen中,却取消了SO_REUSEPORT设置

int SockUtil::listen(const uint16_t port, const char *local_ip, int back_log) {
...
setReuseable(fd, true, false);
...
}

有点不理解,客户端没必要使用SO_REUSEPORT吧,服务端才需要,谢谢解惑。

TRANS_BY_GITHUB_AI_ASSISTANT

@xia-chu
Copy link
Member

xia-chu commented Sep 9, 2024

Let's first look at how the function is implemented, and the related functional description:

int SockUtil::setReuseable(int fd, bool on = true, bool reuse_port = true) {
    int opt = on ? 1 : 0;
    int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
    if (ret == -1) {
        TraceL << "setsockopt SO_REUSEADDR failed";
        return ret;
    }
#if defined(SO_REUSEPORT)
    if (reuse_port) {
        ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
        if (ret == -1) {
            TraceL << "setsockopt SO_REUSEPORT failed";
        }
    }
#endif
    return ret;
}
  • SO_REUSEADDR is mainly used to make the port available immediately after the socket is closed, or to allow multiple sockets to bind to the same address in some cases.
  • SO_REUSEPORT is mainly used to allow multiple sockets to listen on the same port in parallel, thereby achieving better load balancing and performance.

先让我们看看函数怎么实现的,以及相关功能描述:

int SockUtil::setReuseable(int fd, bool on = true, bool reuse_port = true) {
    int opt = on ? 1 : 0;
    int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
    if (ret == -1) {
        TraceL << "setsockopt SO_REUSEADDR failed";
        return ret;
    }
#if defined(SO_REUSEPORT)
    if (reuse_port) {
        ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
        if (ret == -1) {
            TraceL << "setsockopt SO_REUSEPORT failed";
        }
    }
#endif
    return ret;
}
  • SO_REUSEADDR is mainly used to make the port available immediately after the socket is closed, or to allow multiple sockets to bind to the same address in some cases.
  • SO_REUSEPORT is mainly used to allow multiple sockets to listen on the same port in parallel, thereby achieving better load balancing and performance.

TRANS_BY_GPT4

Let's first look at how the function is implemented, and the related functional description:

int SockUtil::setReuseable(int fd, bool on = true, bool reuse_port = true) {
    int opt = on ? 1 : 0;
    int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
    if (ret == -1) {
        TraceL << "setsockopt SO_REUSEADDR failed";
        return ret;
    }
#if defined(SO_REUSEPORT)
    if (reuse_port) {
        ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
        if (ret == -1) {
            TraceL << "setsockopt SO_REUSEPORT failed";
        }
    }
#endif
    return ret;
}
  • SO_REUSEADDR 主要用于使端口在套接字关闭后立即可用,或允许在某些情况下多个套接字绑定到同一个地址。
  • SO_REUSEPORT 主要用于允许多个套接字在同一端口上并行监听,从而实现更好的负载均衡和性能。

先让我们看看函数怎么实现的,以及相关功能描述:

int SockUtil::setReuseable(int fd, bool on = true, bool reuse_port = true) {
    int opt = on ? 1 : 0;
    int ret = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
    if (ret == -1) {
        TraceL << "setsockopt SO_REUSEADDR failed";
        return ret;
    }
#if defined(SO_REUSEPORT)
    if (reuse_port) {
        ret = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &opt, static_cast<socklen_t>(sizeof(opt)));
        if (ret == -1) {
            TraceL << "setsockopt SO_REUSEPORT failed";
        }
    }
#endif
    return ret;
}
  • SO_REUSEADDR 主要用于使端口在套接字关闭后立即可用,或允许在某些情况下多个套接字绑定到同一个地址。
  • SO_REUSEPORT 主要用于允许多个套接字在同一端口上并行监听,从而实现更好的负载均衡和性能。

TRANS_BY_GPT4

TRANS_BY_GITHUB_AI_ASSISTANT

@xia-chu
Copy link
Member

xia-chu commented Sep 9, 2024

This change was introduced in 0e040d2 to fix the issue where listening on a port twice would not throw an error.

这个修改是在 0e040d2 引入的,目的是解决端口被重复监听不报错的问题。

TRANS_BY_GPT4

This change was introduced in 0e040d2 to fix the issue where listening on a port twice would not throw an error.

这个修改是在 0e040d2 引入的,目的是解决端口被重复监听不报错的问题。

TRANS_BY_GPT4

TRANS_BY_GITHUB_AI_ASSISTANT

@xia-chu
Copy link
Member

xia-chu commented Sep 9, 2024

SO_REUSEPORT should be turned off by default and should only be turned on in rare cases.
Currently, there is only a need for multiple Socket fds to listen to the same port in the case of a UDP server.

SO_REUSEPORT 应该默认都关闭,只有非常少见的情况下才应该开启。
Currently, only in the case of a UDP server is there a need for multiple Socket fds to listen to the same port.

TRANS_BY_GPT4

SO_REUSEPORT should be turned off by default and should only be turned on in rare cases.
Currently, there is only a need for multiple Socket fds to listen to the same port in the case of a UDP server.

SO_REUSEPORT 应该默认都关闭,只有非常少见的情况下才应该开启。
目前也就udp server的情况下才存在多个Socket fd监听同一个端口的需求

TRANS_BY_GPT4

TRANS_BY_GITHUB_AI_ASSISTANT

@ddwapple
Copy link
Author

ddwapple commented Sep 11, 2024

SO_REUSEPORT should be turned off by default and should only be turned on in rare cases. Currently, there is only a need for multiple Socket fds to listen to the same port in the case of a UDP server.

SO_REUSEPORT 应该默认都关闭,只有非常少见的情况下才应该开启。
目前也就udp server的情况下才存在多个Socket fd监听同一个端口的需求

TRANS_BY_GPT4

void TcpServer::start_l(uint16_t port, const std::string &host, uint32_t backlog) {
// 监听地址,产生fd,然后attachEvent(sock),也就是放在对应epoller里面监听fd
if (!_socket->listen(port, host.c_str(), backlog)){}
for (auto &pr: _cloned_server) {
        // 启动子Server
       //  再次在各个子server里面监听fromSock_l(sock);->attachEvent(sock);
        pr.second->_socket->cloneSocket(*_socket);
}
}

Looking at the code, after the main server listens, it calls fromSock_l->attachEvent to listen to the fd.
It iterates through the child servers and also listens to the listened fd, so won't this prevent the thundering herd effect? If the server doesn't set SO_REUSEPORT and doesn't use the EPOLLEXCLUSIVE flag in EPOLL, when a connection comes in, won't there be a problem? Or did I miss something? Thank you for your guidance.

SO_REUSEPORT should be turned off by default and should only be turned on in rare cases. Currently, there is only a need for multiple Socket fds to listen to the same port in the case of a UDP server.

SO_REUSEPORT 应该默认都关闭,只有非常少见的情况下才应该开启。
目前也就udp server的情况下才存在多个Socket fd监听同一个端口的需求

TRANS_BY_GPT4

void TcpServer::start_l(uint16_t port, const std::string &host, uint32_t backlog) {
// 监听地址,产生fd,然后attachEvent(sock),也就是放在对应epoller里面监听fd
if (!_socket->listen(port, host.c_str(), backlog)){}
for (auto &pr: _cloned_server) {
        // 启动子Server
       //  再次在各个子server里面监听fromSock_l(sock);->attachEvent(sock);
        pr.second->_socket->cloneSocket(*_socket);
}
}

看代码里面,主Server listren后,调用fromSock_l->attachEvent监听fd。
遍历子server,同时也都监听了listen后的fd,这样不会引起惊群效应嘛,服务端不设置SO_REUSEPORT,在EPOLL里面也没有使用EPOLLEXCLUSIVE标识,那有个链接过来,不会有问题吗,还是我看漏了,谢谢指导。

TRANS_BY_GITHUB_AI_ASSISTANT

@xia-chu
Copy link
Member

xia-chu commented Sep 13, 2024

After enabling EPOLLEXCLUSIVE, there are other problems, such as modifying events will fail, so the EPOLLEXCLUSIVE flag is removed.
You can refer to: #226

开启EPOLLEXCLUSIVE后又有其他问题,比如说修改事件会失败,所以去掉EPOLLEXCLUSIVE标记了。
你可以参考下: #226

TRANS_BY_GITHUB_AI_ASSISTANT

@alexliyu7352 alexliyu7352 changed the title setReuseable设置socket fd是否写反 setReuseable sets whether the socket fd is written in reverse. Sep 14, 2024
@ddwapple
Copy link
Author

After enabling EPOLLEXCLUSIVE, there are other problems, such as modifying events will fail, so the EPOLLEXCLUSIVE flag is removed. You can refer to: #226

开启EPOLLEXCLUSIVE后又有其他问题,比如说修改事件会失败,所以去掉EPOLLEXCLUSIVE标记了。
你可以参考下: #226

TRANS_BY_GITHUB_AI_ASSISTANT

嗯嗯,谢谢。

@xia-chu xia-chu closed this as completed Sep 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants