从 Internet 连接到 Android 应用程序的套接字:可能吗?

Connect to Android App's Socket from Internet: Possible?

我正在尝试开发一个 Android(服务器)应用程序,它将接受来自 Internet 直接 的 TCP 连接。几年前我尝试过这个,但并不开心。 这可能吗?

我当时在 Whosebug 和其他地方以不同的方式问过这个问题,但从未得到满意的答案。答案分为两类:

我试过的

备注:

我目前的理论 (9/23/19)

我目前的拙见是这里有一个类似 NAT 的实体在起作用。要么:

无论哪种情况,根据该理论,入站 TCP 连接不会转发到设备的本地网络,但出站 连接会通过正好。

总结

也许答案还是一样,但我想我会再问一次,以防万一情况发生了变化,或者现在有人有了更好的见识,

这取决于您的移动 phone 提供商分配给您的 IP 类型

要让您的移动设备接受来自外部的 TCP 连接,只有当您的提供商为您分配一个 public IP 时才有可能,但这越来越不可能,因为由于可用 IP 短缺,许多提供商分配了一个私有 IP,就像您的 phone 在局域网内一样,在这种情况下,您的 TCP 端口无法从外部访问。

像 whatsmyip 这样的网站会告诉您 public IP,您的供应商最终将您连接到互联网的 IP,但它可能与您的供应商分配给您的 IP 不同 phone。

要知道您是否在专用网络中,请从 Play 商店安装一个名为 "PingTools Network Utilities" 的应用。 当你启动它时,你会看到你的 phone 的 IP,如果它与 whatsmyip IP 不同或者是 IPV6 IP,这意味着你的提供商为你分配了一个私有 IP,一个无法访问的 IP。

...总是谈论通过蜂窝网络而不是通过 WiFi 进行连接

你需要一个静态 ip(public ip) 地址。

移动设备的 IP 地址不是静态的,所以你不能。

让它发挥作用。

运行 静态 IP 上的 Web 服务器并将查询路由到您的应用程序(隧道)。

当 android 应用程序启动时,您 android 应用程序需要向网络服务器注册。

现在服务器知道您的 android 设备可用性,来自另一端的查询将被重定向。

为 DynDNS 或类似软件编写一个简单的客户端,以便为其提供名称解析。然后您可以使用 NanoHTP 或原始套接字来提供页面。如果您在 DSL 路由器后面,您可能需要使用 TR-604 读取外部 IP(除非 DynDNS 最终可能 return 源 IP)并为端口 [= 上的传入流量设置 NAT 端口转发10=]。在家里这比通过 UMTS 更容易设置,因为一些 UMTS 网络没有 public IP 地址,但可能有私有 IP 地址。

的确,您无法建立任何在主网络后方(即在 NAT 后方)侦听的 TCP 或 UDP 连接。如今,所有 ISP 都会为连接到它的每个设备(由于 IP 短缺)分配一个专用 IP,从而在 NAT 后面创建一个设备专用网络。 (IPv6完全采用后情况会有所改变,每台设备都成为主网的一部分)

由于 NAT 不允许入站连接,因此使用一些 NAT 遍历技术解决了问题,例如:

  • 端口转发
  • TCP/UDP打孔

在端口转发过程中,我们需要处理路由器设置,将特定端口上的连接转发到内部网络节点上的相同端口。主要用于游戏、VoIP、p2p应用。

在打孔技术(无需处理路由器设置)中,我们使用不在任何 NAT 后面的外部服务器来获取设备的 IP 地址(public 和私有地址)在 NAT 后面。此外,两台主机在各自的 NAT 设备中彼此创建自己的出站会话。由于 NAT 设备允许出站会话,因此会存储该会话,并且此同一会话将用于进一步的双向通信。 More information about Hole punching.

(2019 年 9 月 26 日更新)

我发布这个 "answer" 本身并不是一个答案,而是征求建设性的批评 and/or 肯定。我在下面所做的任何陈述都应该隐含地以 "I humbly believe that...".

为前缀

昨天,我个人顿悟了。我终于通过我厚厚的头骨明白了一些回应者所说的话。下面我介绍一下我的新认识。

此前我认为 AT&T 的移动数据网络只是对互联网的直接扩展,通过基站和中继线实现。现在我意识到它是一种封闭的、私有的数据传输机制。由于它归 AT&T 所有,他们可以实施他们选择的 任何 协议,包括从他们的头端到我注册的 phone 的 "private" 数据连接。这些连接类似于典型桌面 NAT 路由器上的 LAN 端端口。头端(即他们的 NAT 路由器)是 唯一 可以从 Internet 访问的实体。

互联网和我的 phone 之间的头端连接是通过这些 AT&T 专用连接 实现的。 "public IP" 为我的设备(我相信附近的设备)报告的实际上指向 AT&T 头端,在我的例子中是 150 英里外的迈阿密)。头端转发 outbound 连接从我的 phone 到 Internet,但不转发 inbound 连接请求。

关于我的"Public IP"

我认为这不存在,实际上是一个毫无意义的概念。如果您无法连接到这样的地址,那么它有什么意义呢?

总结

我现在相信我原来问题的答案是 "No way, Jose"。这不是由于寻址问题,而是 AT&T 不会 将传入连接路由到设备。他们也通过他们的私人网络为设备提供静态IP(鉴于上述情况,这无论如何都没有多大意义)。

如果此原始答案中的任何陈述不正确,请告诉我哪一个以及为什么不正确

我想给出一个非技术性的回答,因为我自己对网络理论不是很精通

一件事是,如果您想要 运行 服务器,Internet 提供商通常会期待额外的现金 - 因此强制断开消费者订阅,如 DSL(在此过程中更改 IP)。

接下来是建立连接并将数据发送到服务器在移动设备上非常不可靠。您可以让 android 检查您是否有网络。如果它说不,你不需要尝试 - 不意味着不。但是是并不意味着什么!

我使用 android 编写资产跟踪软件。通常我想每分钟向该服务器发送一个位置。所以我尝试打开一个端口。 Android 阻塞在新的 Socket 上,它可能会持续 2 分钟直到超时发生,即使我事先检查了 ConnectivityManager 并且它让我 isConnected() == true。

如果我有一个套接字甚至在一秒钟前收到了一些东西:我可以写入那个套接字并且没有错误但是没有得到答案,再写一次,没有错误没有回答一次又一次..在像 2分钟我在日志中同时收到一大堆错误。

从互联网连接来看,坐在公共汽车上看望我母亲就像开车经过第三世界国家。它可能说 4g 和 3 格,但 chrome 不会加载页面,或者它说 2g,只有 2 格,但浏览器完全没有问题..

整个 android 网络-os(我想苹果必须完全相同)的编程更像是:“这里 android 我想发送这个”并且 android 说“好的”,但在想“我会尽快发送它”:D