计算机网络实践之元气骑士公网异地联机(二) 两种方案可行性分析

前言

在上一篇中,我已经通过分析得知了元气骑士在局域网联机过程中是通过UDP进行交互的,只要我们能正确的转发这些UDP消息,就能实现异地公网的联机了。转发UDP消息通常有两种方案:一个是通过UDP穿透,建立起两部手机的对等连接,让两部手机直接向对方发送UDP;另一个是搭建一个代理服务器,手机先将UDP消息发送给服务器,服务器将消息再转发给另外一部手机。通过本篇的分析可以得知, 对于元气骑士公网异地联机而言,方案一是不可行的 ,最后我只能选择方案二进行尝试。方案一虽然不可行,但是通过对方案一的可行性分析,学习了NAT与UDP穿透的相关知识,也算收获匪浅,故写下本篇博文记录一下。如果对NAT以及UDP的穿透不感兴趣可跳过本篇。

方案一:UDP穿透,实现异地联机

为什么实现联机需要进行UDP穿透

由于互联网用户的急速增长,每个用户又拥有众多上网设备(笔记电脑、智能手机、ipad等),从20世纪80年代起,一个很明显的问题是IPv4地址在以比设计时的预计更快的速度耗尽。

为了缓解这一问题,计算机网络领域提出了网络地址转换(Network Address Translation,缩写为NAT)技术。目前大多数手机、电脑所分配到的IP其实都经过了多次NAT转换。

例如:
在这里插入图片描述在这里插入图片描述

10.125.225.198 是我在设置-》关于手机-》状态信息中所得到的ip地址,是移动运营商分配给我的ip地址,而我去浏览器查询ip时却显示的是 223.104.175.159 ,这说明在运营商那,我的ip地址经过了至少一次的转换。

显然,10.125.225.198 是内网ip,223.104.175.159 才是能上网的公网ip,此刻我的手机并未连接路由器,使用的是移动流量。如果手机连接了路由器,则内网ip为192.168.*.* 公网ip为路由器拨号所得的ip,在网络请求时,路由器会将将我们的地址进行了一次转换,这种地址转换技术就是NAT。

当内网设备向公网发起请求的时候,不同的内网ip会被路由器转化为同一个外网ip(因为路由器拨号上网只得到了一个外网ip),那么问题来了,如果外部网络想向内网设备请求会怎样呢?如果不考虑其他技术或协议的话,外部网络设备只知道一个外网ip, 当外部网络设备向这个外网ip发送数据的时候,路由器会懵逼,因为它并不知道该把这个源自外部消息转发给内网哪个设备。

现实情况是,我们的路由器不会那么傻,大多数情况下(几乎百分百)我们能正确收到外部网络返回的响应信息(外部网络的响应信息,是由外部服务器向本地主机发送的信息,“响应”说明服务器给本地主机发送信息之前,本地主机必须先发起请求)。

NAT有三种类型:静态NAT(StaticNAT)、动态地址NAT(PooledNAT)、网络地址端口转换NAPT(Port-LevelNAT)

我们最常见的是网络地址端口转换NAPT,NAPT在处理内网设备向外网的请求时,会将地址和端口一并进行转换,假如A主机的发送端口是80,可能转换后发送端口就变成了6000,若B主机也发送了一个请求,那么B主机的发送端口可能就是60001了,总之在一个时间段内,对于不同主机对外网的请求来说,NAPT一定会给他们分配不同的发送端口, 这样服务器返回响应信息的时候,就可以根据信息的目的端口,来准确的识别将信息转发给哪个一个设备了 。而穿透就是指,让路由器知道当两个不同内网的设备进行通信时,该如何正确的转发消息。

UDP穿透流程

当下,我们面临情况是手机与手机点对点的通信,无论用手机流量还是用wifi,总之,是内网设备对内网设备的P2P通信,这种情况的UDP穿透需要一个 具有外网IP的 服务器,其穿透流程大体如下:
在这里插入图片描述

1. 主机A通过路由器向服务器发送UDP数据报
2. 路由器A转换地址与端口
3. 服务器记录下路由器A的地址和端口
4. 主机B通过路由器向服务器发送UDP数据报
5. 路由器B转换地址与端口
6. 服务器记录下路由器B的地址和端口
7. 服务器向B发送A的端口和地址
8. 路由器B会把服务器的信息转发给主机B
9. 主机B向服务器返回的A的端口和地址发送请求
10. 路由器B将消息转发给路由器A(消息会被路由A抛弃)
11. 服务器向A发送B的端口和地址
12. 路由器A会把服务器的信息转发给主机A
13. 主机A向服务器返回的B的端口和地址发送请求
14. 路由器A将消息转发给路由器B(消息会被路由B转发)
15. 主机B会接受到经过路由B转发的、主机A的消息
16. 此后主机A和主机B就可以无需经过服务器了,可以直接通信了

要实现上述穿透流程,有一个必要条件,就是路由器B向服务器发送请求时转换的地址和端口,必须和路由器B向路由器A发送请求时的地址和端口一致,也就是说,对于同一内网ip,在段时刻内即使请求目标是不同的外网IP,转后的端口也相同。 但事实上,并不是所有的NAPT都能满足这个条件。

NAT类型

NAPT总共有4中类型,分别是:

NAPT类型别称端口转换策略将外网设备消息转发给内网设备A的条件
Full Cone NATNAT1所有来自同一 个内网设备的请求均被转换为同一端口A曾经用该端口向外部任意地址发送过消息
Restricted Cone NATNAT2所有来自同一 个内网设备的请求均被转换为同一端口A曾经用该端口向消息的发送地址发送过消息
Port Restricted Cone NATNAT3所有来自同一 个内网设备的请求均被转换为同一端口A曾经用该端口向消息的发送地址与发送端口发送过消息
Symmetric NATNAT4只有来自于同一个内网设备、针对同一目标的请求才被转换为同一端口。来自同一 个内网设备、针对不同目标的请求会被转换为不同端口A曾经用该端口向消息的发送地址与发送端口发送过消息

根据端口转换策略,可将NAPT分为锥型(Cone)和对称型(Symmetric),锥型包括NAT1、NAT2、NAT3,锥型NAPT会将所有来自同一 个内网设备的请求均转换为同一端口 ,而对称型NAP也称NAT4是只有来自于同一个内网设备、针对同一目标的请求才被转换为同一端口。

如果想实现UDP穿透,至少两端之中有一端是锥型NAT才可以,所以在确定方案可行性之前,需要测定手机流量的NAPT类型。

NAPT类型测试

测试NAPT类型有专门的协议:STUN ,简单的办法就是,去网上下载一个NAT类型测试工具,这个CSDN就有资源。因为考虑到元气骑士联机,所以用电脑连接手机热点,然后在电脑上用NAT测试工具试一试就能知道个大概,

但非常不幸,手机热点是对称型的。

在这里插入图片描述

通过查阅资料,基本确定3G/4G流量都是对称型的,所以这个方案凉凉。

结论

因为手机流量、手机热点都是对称型NAT,所以无法实现UDP穿透,故该方案不可行。

方案二:建立代理服务器,转发UDP消息

幸好通过之前的分析,已经得知元气骑士在局域网联机的时候,只会发送23333端口的广播信息,和7777端口的单一目标信息,但是要是公网联机,需要三个转发机,分别是:

  • 主机A和主机B:用于将手机的消息转发给服务器,将服务器的消息转发给手机
  • 服务器:用于将主机A的消息转发给主机B,将主机B的消息转发给主机A

所以代理服务器的工作流程大致如下:

步骤操作
1主机A与服务建立连接
2主机B与服务器建立连接
3手机A创建游戏房间,发送到23333端口的广播消息
4主机A监听23333端口,发送端口不变,将接受的消息发往服务器的34444端口,并记录手机A的内网地址
5服务器监听34444端口,发送端口不变,将接受的消息发往主机B的34444端口
6主机B监听34444端口,发送端口不变,将接受的消息转发为发送到23333端口的广播
7手机B监听23333端口,发送端口不变,接受到23333端口的消息后,向主机B的7777端口发送加入房间的消息
8主机B监听7777端口,同时开始监听消息的发送端口,并将接受的消息发送端口不变的发往服务器的8888端口,并记录手机B的内网地址
9服务器监听8888端口,同时开始监听消息的发送端口,并将接受的消息发送端口不变的发往主机A的8888端口
10主机A监听8888端口,同时开始监听消息的发送端口,并将接受的消息发送端口不变的发往手机A的7777端口
11手机A监听7777端口,手机A收到消息立即向消息来源返回消息
12主机A监听之前的发送端口,将接受的消息不改变目的端口和发送端口的转发给服务器
13服务器监听之前的发送端口,将接受的消息不改变目的端口和发送端口的转发给主机B
14主机B监听之前的发送端口,将接受的消息不改变目的端口和发送端口的转发给手机B

整理一下,给出每个代理服务器的任务:
在这里插入图片描述

转发机监听端口
主机A23333、8888、8888端口消息的发送端口p
主机B34444、7777、7777端口消息的发送端口p
服务器34444、8888、8888端口消息的发送端口p
转发机转发逻辑
主机A23333->服务器:34444;8888->手机A:7777;p->服务器:p;
主机B34444->内网广播:23333;7777->服务器:8888;p->手机B:p;
服务器34444->主机B:34444;8888->主机A:8888;p->主机B:p;

结语

方案一虽然不可行,但是通过对方案一的可行性分析,学习了NAT与UDP穿透的相关知识,也算收获匪浅。方案二虽然可行,但是因为要持续占有服务器资源,所以如果将此方案列为第二方案。方案二是假设A和B两个玩家的联机情况,我的想法是,先完成双人联机的情况,再此基础上再逐步扩展。转发机我打算用JAVA实现,因为JAVA网络与多线程的编程封装了很多实用的API,且JAVA具有良好的移植性。确认了实现方案之后,下一篇将会考虑到路由器的NAT问题,对该方案进行更为全面的讨论,完善转发机的转发规则。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值