目录


准备工作

下面是用于测试的多线程TCP服务器(比较简易,未处理粘包问题),其并发模型是:每个连接由一个单独的线程处理。该程序接受两个命令行参数:要监听的IP地址、端口:

下面是用于向测试服务器发送请求的测试客户端,该程序需要四个命令行参数:客户端IP、客户端端口、服务端IP、服务端端口:


SO_REUSEADDR选项

Linux manual中的描述如下:

翻译成中文如下:

也就是:

在没设置SO_REUSEADDR选项的情况下,不同的socket不能绑定相同的地址。

在设置SO_REUSEADDR选项的情况下,对于一个地址,一旦存在绑定它的监听socket,那么其它socket不能再绑定它;否则,可以绑定。

并且,INADDR_ANY(表示所有本地地址)与所有本地地址冲突。

下面使用[准备工作]中的两个测试程序,进行验证:

  1. 启动两个服务器,分别监听127.0.0.1:2345和127.0.0.1:2346:

    打开两个终端,分别执行:

  2. 启动两个客户端,都绑定127.0.0.1:3456,分别连接到127.0.0.1:2345和127.0.0.1:2346:

    打开两个终端,分别执行:

    执行第二个命令时,会出现类似下面的错误:

    这次实验验证了没设置SO_REUSEADDR选项的情况

  3. client.py文件中的request()函数的第二行取消注释,也就是给client socket设置SO_REUSEADDR选项。然后按照步骤2,重新执行测试

    通过netstat命令,也可以看出,两个客户端socket绑定了相同的地址:

    这次实验验证了设置SO_REUSEADDR选项的情况

需要特别强调的是:


SO_REUSEPORT选项

Linux manual中的描述如下:

翻译成中文如下:

需要特别强调的是:

下面使用[准备工作]中的两个测试程序,进行验证:

  1. threaded_server.py文件中的ThreadedServer类的run()方法的第二行取消注释,也就是为server socket设置SO_REUSEPORT选项。然后启动两个服务器,都监听127.0.0.1:2345:

    打开两个终端,都执行:

  2. 启动若干个客户端,绑定127.0.0.1:0(绑定0端口时,操作系统会随机分配一个空闲端口),并连接到127.0.0.1:2345:

    打开若干个终端,都执行:


说明

本文中的代码在以下环境下测试通过:


参考文档