socket 端口和地址复用

https://blog.csdn.net/weibo1230123/article/details/79978745

https://blog.csdn.net/weixin_42157432/article/details/115560824

在linux socket网络编程中,大规模并发TCP或UDP连接时,经常会用到端口复用:

int opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &opt, sizeof(opt))) {
    
    
    perror("setsockopt");
    return -1;
}

端口复用可以这样理解:

在A机进行客户端网络编程,假如它使用的本地端口号为1234,如果没有开启端口复用的话,它用本地端口1234去连接B机再用本地端口连接C机时就不可以了。

若开启了端口复用的话在本地端口1234访问B机的情况下还可以用本地端口1234访问C机。

如果是服务器程序中监听的端口,即使开启了复用,也不可以用该端口向外发起连接。

接下来看看setsockopt函数的参数意义:

/* Set socket FD's option OPTNAME at protocol level LEVEL
   to *OPTVAL (which is OPTLEN bytes long).
   Returns 0 on success, -1 for errors.  */
extern int setsockopt (int __fd, int __level, int __optname,
		       const void *__optval, socklen_t __optlen) __THROW;

__optname常见的有两个:

SO_REUSEADDR:地址复用

SO_REUSEPORT:端口复用

一般来说,一个{addr,port}只能被一个套接字绑定,无法重用。

不同的套接字只能绑定到不同的的{addr,port}

SO_REUSEADDR 和 SO_REUSEPORT

SO_REUSEADDR提供如下四个功能:

SO_REUSEADDR允许启动一个监听服务器并捆绑其众所周知端口,即使以前建立的将此端口用做他们的
        本地端口的连接仍存在。这通常是重启监听服务器时出现,若不设置此选项,则bind时将出错。
 
SO_REUSEADDR允许在同一端口上启动同一服务器的多个实例,只要每个实例捆绑一个不同的本地IP地址
            即可。对于TCP,我们根本不可能启动捆绑相同IP地址和相同端口号的多个服务器。
 
SO_REUSEADDR允许单个进程捆绑同一端口到多个套接口上,只要每个捆绑指定不同的本地IP地址即
            可。这一般不用于TCP服务器。
 
SO_REUSEADDR允许完全重复的捆绑:当一个IP地址和端口绑定到某个套接口上时,还允许此IP地址和端
            口捆绑到另一个套接口上。一般来说,这个特性仅在支持多播的系统上才有,而且只对UDP套
            接口而言(TCP不支持多播)。

SO_REUSEPORT选项有如下语义:

此选项允许完全重复捆绑,但仅在想捆绑相同IP地址和端口的套接口都指定了此套接口选项才行。
 
如果被捆绑的IP地址是一个多播地址,则SO_REUSEADDR和SO_REUSEPORT等效。

使用这两个套接口选项的建议:

在所有TCP服务器中,在调用bind之前设置SO_REUSEADDR套接口选项;

功能如下:

  • 若监听服务器进入TIME_WAIT状态,可立即重启
  • 同一端口启动同一服务器的多个实例,需要每个实例socket绑定不同的ip地址,一般需要多个网卡支持
  • 支持完全重复的捆绑

当一个IP地址和端口绑定到某个socket上,还允许此IP地址和端口号捆绑到另一个socket上。

一般来说,这个特性仅在支持多播的系统上才有用,而且只针对UDPsocket,TCP不支持多播

对于监听线程来说,可重用socket被称为监听桶(listener bucket),即每一个socket都是一个桶。以event模型为例,假设目前有3个子进程,吗,每个进程中都有一个监听线程和多个工作线程。

  • 端口未重用情况下:

某个时刻,该监听socket仅能由某一个进程持有,当该进程接收到请求后,才让出监听权,相当于各个监听者只能轮流监听。
在这里插入图片描述

  • 端口重用情况下
    这里我们重用地址和端口两次,三个监听者都可以同时监听了。
    三个监听桶下,各个进程不用让出监听权,看上去减轻了互斥锁的争用,避免了饥饿,还能更高效地监听,实现负载均衡,从而减轻了监听线程的压力,但是由于监听的过程中需要消耗CPU,若是单核CPU是无法体现出端口复用的优势的,反而会由于切换监听线程而降低性能。
    在这里插入图片描述
    所以若要使用端口复用,需要考虑几点:
  • 是否将监听进程/线程隔离在各自CPU中
  • 重用次数
  • CPU核数

Supongo que te gusta

Origin blog.csdn.net/qq_42604176/article/details/121051031
Recomendado
Clasificación