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

2021-04-04 23:30:50 +08:00
 LeeReamond

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

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

========

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

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

3525 次点击
所在节点    Python
13 条回复
opengps
2021-04-04 23:34:18 +08:00
我的做法:
1,服务器程序绑定 0.0.0.0,为了兼容所有网卡都能通信,对外网就可以只提供一个端口即可,无论发布在什么网络结构下
2,服务器读取下本地所有网卡的 ip,构造一个 list 存储所有 ipv4 的地址,存到共享缓存里,用来内部直连通信用
ClericPy
2021-04-04 23:42:09 +08:00
本来点进来以前以为会聊服务发现或者反向代理... 你这个似乎就是想把公网 IP 发给客户端让他访问? 防火墙如果已经开了公网端口的话, 随便打个查看 IP 的网址可以不? 除了 ipip 什么的, 我偶尔会用 httpbin.org/get 里面给我的 IP
LeeReamond
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
2021-04-05 00:57:47 +08:00
bind 使用未指定地址就是为了绑定到所有 link 上。
如果希望知道有哪些地址的话调用 ip -j link ( json 输出,依赖 iproute2 实用工具),觉得不优雅的也可以用 libnl 读取。
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
2021-04-05 11:41:12 +08:00
我感觉你要上服务发现
DCjanus
2021-04-05 12:19:39 +08:00
搜索 stun 就可以了,感觉就是常见的 P2P 场景
ho121
2021-04-05 12:22:35 +08:00
端口转发要考虑么?
pursuer
2021-04-05 13:58:12 +08:00
为什么 “请求网卡上的地址”是不太优雅的方法?我觉得是挺正常的方法

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

https://imgur.com/cGZgvhx
pursuer
2021-04-06 08:27:25 +08:00
@LeeReamond
python 作为胶水语言,缺啥加啥也是正常的,可以试试个 pyuv
import pyuv
pyuv.util.interface_addresses()
就可以读 ip 了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/768030

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX