V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
LeeReamond
V2EX  ›  Python

服务绑定到 0.0.0.0 的话,有什么办法自动获取到其他人可以接入的 IP 地址吗?

  •  
  •   LeeReamond · 2021-04-04 23:30:50 +08:00 · 3506 次点击
    这是一个创建于 1110 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如题,想要做一种使用场景是,我开了一个服务进程,利用 tcp 与客户端通信。

    当然理论情况下是可以由用户设定好这个服务绑定到比如哪个 IP 的哪个端口,但是还想要做一种功能是不用用户设置,直接绑定到 0.0.0.0 并随意选择一个端口,然后在服务绑定好之后再通知客户端说我绑定到哪里了,如果这样的话,那就可以随意开关任意数量的服务端而不用考虑接口地址的设置问题。

    ========

    目前端口问题比较好搞定,比如用户绑定到 127.0.0.1:0,系统自动分配一个端口,绑定后再获取就确定好位置了。但是 IP 的话如果绑定到 0.0.0.0 则没法用类似逻辑。

    不太优雅的方法似乎是请求网卡上都有哪些地址?感觉不太好,还有优雅一些的解决方案吗。

    13 条回复    2021-04-06 08:27:25 +08:00
    opengps
        1
    opengps  
       2021-04-04 23:34:18 +08:00
    我的做法:
    1,服务器程序绑定 0.0.0.0,为了兼容所有网卡都能通信,对外网就可以只提供一个端口即可,无论发布在什么网络结构下
    2,服务器读取下本地所有网卡的 ip,构造一个 list 存储所有 ipv4 的地址,存到共享缓存里,用来内部直连通信用
    ClericPy
        2
    ClericPy  
       2021-04-04 23:42:09 +08:00
    本来点进来以前以为会聊服务发现或者反向代理... 你这个似乎就是想把公网 IP 发给客户端让他访问? 防火墙如果已经开了公网端口的话, 随便打个查看 IP 的网址可以不? 除了 ipip 什么的, 我偶尔会用 httpbin.org/get 里面给我的 IP
    LeeReamond
        3
    LeeReamond  
    OP
       2021-04-05 00:50:58 +08:00
    @opengps
    @ClericPy 理论上确实是想实现“让别人发现我正在提供服务”这个功能。比如设计一个简单的使用场景,在一个多进程基于 tcp 的通信中,我现在有一个固定的中心服务器,比如绑定到 center.service.com:443,我想实现的效果是每个服务器,即使在不同的机器中,只需要运行 server = center.connect()就可以告知目前在线的所有人连接我这个服务的方式。

    理论上几种做法,一种是由于大家都和 center 有连接,所有流量都经由 center 代理,这种在多节点通信情况下效率太低,不作考虑。另一种是由服务端上线时自己设定好,比如 server = center.connect(my_ip='192.168.0.100'),然后绑定服务到这个 IP,这个感觉又太麻烦了,理想的情况下就是 server 不用进行任何设置直接启动,然后自动绑定 0.0.0.0 的某个端口,并且自动获取到其他人访问哪个 IP 可以经由 0.0.0.0 转接。

    可能说的不太清楚,需求比较怪,两位见谅。
    jim9606
        4
    jim9606  
       2021-04-05 00:57:47 +08:00
    bind 使用未指定地址就是为了绑定到所有 link 上。
    如果希望知道有哪些地址的话调用 ip -j link ( json 输出,依赖 iproute2 实用工具),觉得不优雅的也可以用 libnl 读取。
    jim9606
        5
    jim9606  
       2021-04-05 01:24:57 +08:00
    如果你这个应用的全在一个局域网的话,可以考虑用 mDNS 发布一个 service(DNS SRV 记录),例如这样:
    avahi-publish-service center _myapp._tcp 5666 parm1=val1 parm2=val2

    其他端点用支持 mDNS 的查询器查询这个 SRV 记录:
    avahi-browse -r _myapp._tcp
    zachlhb
        6
    zachlhb  
       2021-04-05 11:41:12 +08:00 via iPhone
    我感觉你要上服务发现
    DCjanus
        7
    DCjanus  
       2021-04-05 12:19:39 +08:00 via Android
    搜索 stun 就可以了,感觉就是常见的 P2P 场景
    ho121
        8
    ho121  
       2021-04-05 12:22:35 +08:00 via Android
    端口转发要考虑么?
    pursuer
        9
    pursuer  
       2021-04-05 13:58:12 +08:00
    为什么 “请求网卡上的地址”是不太优雅的方法?我觉得是挺正常的方法

    如果要去中性化的方案,并且是在局域网内,可以使用组播协议
    no1xsyzy
        10
    no1xsyzy  
       2021-04-05 17:41:41 +08:00
    解决方案应当和网络拓扑有关,如果你所有链接都是 N 层 NAT 那天神难救。
    所有机器的接口 IP 都是相互可见的话,直接拿本机 IP 接口就行;如果有虚拟网络接口会导致混淆,大概也需要分辨一下虚拟接口和真实接口。
    或者让中心服务器去理解谁 connect 进来了,center 拿 src 当默认服务提供点;如果到 center 有 NAT 就不行了。
    再解除更多假设,就会跟 P2P 组网产生类似的情况了,不如直接搞个 P2P 组网设置。
    LeeReamond
        11
    LeeReamond  
    OP
       2021-04-05 20:25:21 +08:00
    @pursuer 因为发在 py 专区,py 似乎是没有标准库实现,要跨进程调用的话似乎就不那么优雅了
    ipwx
        12
    ipwx  
       2021-04-05 21:44:51 +08:00
    @LeeReamond 用 python 可以啊,绑定到 0.0.0.0:0 就行了。

    https://imgur.com/cGZgvhx
    pursuer
        13
    pursuer  
       2021-04-06 08:27:25 +08:00
    @LeeReamond
    python 作为胶水语言,缺啥加啥也是正常的,可以试试个 pyuv
    import pyuv
    pyuv.util.interface_addresses()
    就可以读 ip 了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   962 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:29 · PVG 04:29 · LAX 13:29 · JFK 16:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.