8

我的python测试代码:

import socket

s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind(('192.168.1.1', 80)) 
s1.listen(5)

s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.bind(('0.0.0.0', 80)) 
s2.listen(5)

我收到了这个错误:

fpemud-workstation test # ./test.py
Traceback (most recent call last):
  File "./test.py", line 11, in <module>
    s2.bind(('0.0.0.0', 80)) 
  File "/usr/lib64/python2.7/socket.py", line 224, in meth
    return getattr(self._sock,name)(*args)
socket.error: [Errno 98] Address already in use

192.168.1.1 是我的 eth0 接口的 ip 地址。
我认为 0.0.0.0:80 和 192.168.1.1:80 应该能够共存。
具有 dst-addr 192.168.1.1 的数据包进入套接字 s1,具有其他 dst-addr 的数据包进入套接字 s2。

4

3 回答 3

15

您不能同时绑定到 0.0.0.0:80 和端口 80 上的任何其他 IP,因为 0.0.0.0 涵盖了机器上存在的每个 IP,包括您的 192.168.1.1 地址。这并不表示“任何其他目标地址”,而是表示“此框上的所有接口”。

于 2013-06-25T21:27:39.503 回答
1

尽管其他答案已经说过,但这应该是可能的——只是bind工作方式取决于实现。

例如,在 Windows 上,您的代码可能会按原样正常工作。在某些 *nix 操作系统上,我相信您可以通过设置SO_REUSEADDR套接字选项来使其工作。在 Linux 上,我已经能够使用 socket 选项让它工作SO_REUSEPORT,但仅限于内核版本 3.9 或更高版本。

不幸的SO_REUSEPORT是,当前版本的 python 不直接支持该属性,因此我们必须手动定义它。

基本上你的代码应该是这样的:

# This adds support for the SO_REUSEPORT constant if not already defined.
if not hasattr(socket, 'SO_REUSEPORT'):
  socket.SO_REUSEPORT = 15

s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s1.bind(('192.168.1.1', 80)) 
s1.listen(5)

s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1)
s2.bind(('0.0.0.0', 80)) 
s2.listen(5)
于 2013-06-26T21:28:20.500 回答
1

因为这在术语上是矛盾的。0.0.0.0 表示“接受来自任何本地 IP 地址的连接”。192.168.1.1 表示“只接受发往 192.168.1.1 的连接”。如果有人连接到 192.168.1.1,您到底希望发生什么?

于 2013-06-26T09:49:23.637 回答