SO_REUSEADDR 和 SO_REUSEPORT 的区别和用法实例详细探究讲解

理论:

SO_REUSEADDR:
主要应用场所:服务器主动断开连接后会出现TIME_WAIT状态,时间长达2MSL,此时的ADDRESS(IP + PORT)仍然生效,服务器重启后默认绑定原先的ADDRESS(IP + PORT),会出现address already in use 的错误。如果启用SO_REUSEADDR就能解决这个问题。

SO_REUSEPORT
端口可以重复调用,自动创建线程(类似多线程)。

实例讲解:

这是一个正常的TcpServer。

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);

一、验证SO_REUSEADDR功能:

1.正常的TcpServer启动后关闭状态,会有时间长达2MSL的TIME_WAIT,此时重启服务器会出现bind error:
使用ss命令查看端口状态:

ss -antp | grep 80

注意:第二条信息为系统自动连接,可忽略。
在这里插入图片描述
修改代码如下:

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	int one = 1;
	setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &one,sizeof(one));

启动服务器后关闭,再次启动发现可以启动服务器。用ss 命令查看状态会发现没有TIME_WAIT,如下图:
在这里插入图片描述
结论:SO_REUSEADDR可以解决服务器主动断开连接后时间长达2MSL的TIME_WAIT状态。

二、验证SO_REUSEPORT功能:

两个服务器绑定同一ADDRESS(IP + PORT):出现bind error:
在这里插入图片描述
修改代码如下:

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	int one = 1;
	setsockopt(serv_sock, SOL_SOCKET, SO_REUSEPORT, &one,sizeof(one));

运行结果:发现成功。
在这里插入图片描述

三、验证SO_REUSEADDR和SO_REUSEPORT 是否存在功能交叉:

1.如果换成SO_REUSEADDR 能否让两个服务器绑定同一ADDRESS(IP + PORT)。

修改代码如下:

	serv_sock = socket(PF_INET, SOCK_STREAM, 0);
	int one = 1;
	setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, &one,sizeof(one));
	if (serv_sock == -1) {
		error_handling("socket() error");
	}

运行结果:

在这里插入图片描述
答案:不能成功。

原因:SO_REUSEADDR 只能解决在TIME_WAIT状态下的ADDRESS(IP + PORT)重用。

关闭服务器后,如图:
在这里插入图片描述
说明:SO_REUSEPORT不能结束TIME_WAIT状态。

结论:两个功能不存在交叉功能。

一些好奇的想法

Q1:在仅仅开启SO_REUSEPORT权限时,两个服务器占用同一ADDRESS,如果客户端连接这个ADDRESS,会发生什么情况?哪个服务器在提供服务?

1.开启两个服务器,使用一个客户端进行连接。

在这里插入图片描述
连接结果如下:
在这里插入图片描述
通过进程PID可以发现,最新占用端口的服务器连接了客户端,那么之前的服务器能否用到呢?

2.创建多个客户端尝试:
在这里插入图片描述
通过关闭第一次客户端后,原先与客户端1连接的server2进入TIME_WAIT状态,所以客户端第二次连接就连接到了server1.

发现我写的服务器只能服务一个客户端,显然不符合我的最初疑问,于是换成可以接受多个客户端的服务器,首先加上SO_REUSEADDR和SO_REUSEPORT权限:

 int option = 1;
 setsockopt(httpd, SOL_SOCKET,  SO_REUSEPORT|SO_REUSEADDR, (void *)&option, optlen);

使用四个客户端进行连接,结果如下图:
在这里插入图片描述
可以发现,两个服务器轮流进行提供服务,估计是哪个环节进行了负载均衡处理,但是我的代码里并没有写负载均衡,鉴于笔者知识有限,可以挖一下坑,后续填一下。或者知道的小伙伴留一下言!

总结

SO_REUSEADDR主要用来解决TIME_WAIT,SO_REUSEPORT解决端口可以重复调用问题,两者没有交集和冲突可以根据实际情况进行自由选择。

中间有不严谨的地方还请大家指出!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值