计算机网络实践之元气骑士公网异地联机(一) 初探局域网联机过程

前言

元气骑士作为当下热门的单机游戏,很多人都在琢么怎么和好朋友即使不在一个局域网内也能一起玩耍。目前网上比较成熟的方案是在服务器上搭建VPN,两个手机通过连接VPN来穿透内网,实现彼此的连通,再通过联机工具转发房间的广播信息,如此就能做到公网异地联机了,相关的教程CSDN上都有。

本学期正式学习了计算机网络、windows api编程等课程,正想对这些课程进行一个实践总结,我打算不通过VPN,而是通过自己编程实现元气骑士的公网异地联机。

不过要实现公网异地联机,需要做到转发数据报、穿透内网,本篇主要就是通过封包分析,搞明白这个游戏局域网联机过程,从而弄明白,要转发数据报应该监听哪个端口。

在这个过程中我用了两种方法监听游戏的封包,第一种是电脑开热点,Wireshark监听虚拟wifi所对应的的网卡,这种方法能收到广播信息,但是收不到点对点的UDP数据报,随后根据所学内容对问题进行分析,找到了问题的原因。第二种方法是用tcpdump直接监听安卓设备,导出封包信息,用Wireshark进行分析。

对于当前我们研究的问题来讲,第二种方法才是恰当的方法,使用第二种方法既能对创建房间时的广播进行监听,又能对游戏进行时的P2P进行监听,但是我还是打算把第一种方法写上,一方面是对自己分析过程的记录,另一方面也希望能提醒自己遇到问题不要想当然,要有扎实的理论基础,从理论出发去分析问题。

读者若是不感兴趣可以直接跳过 监听创建房间阶段的封包数据监听游戏进行阶段的封包数据(错误方法) ,可直接从 监听游戏进行阶段的封包数据(正确方法) 开始阅读。

分析工具

Wireshark

tcpdump

逍遥安卓模拟器工作室版

获取封包

监听创建房间阶段的封包数据

搭建测试环境

第一步:配置电脑搭建一个热点,ssid为jack,密码为jackjackjack

@echo off
netsh wlan set hostednetwork mode=allow ssid=jack key=jackjackjack
net start "Windows Firewall"
netsh wlan start hostednetwork
pause

第二步:测试将测试所用的两部安卓手机连接到我们电脑搭建的热点上

第三步:用Wireshark监听虚拟wif所对应的网卡
在这里插入图片描述

监听并分析创建房间时的封包数据

使用手机连接电脑搭建的热点,随后进入元气骑士,创建一个房间,观察到有UDP封包如下:
在这里插入图片描述
192.168.137.110是手机接入热点后,DHCP给手机分配的内网ip,当有玩家创建游戏房间时,玩家所在主机(192.168.137.110)会往192.168.137.255发送一封UDP封包,可见封包内容包括版本号、房间名和一些其他的配置信息。192.168.137.255是一个特殊的地址,它最后8为全是1,说明这是一个广播地址,向这个地址发送的数据会广播给同一网段下(192.168.137.0/24)下的其他主机。

监听游戏进行阶段的封包数据(错误方法)

将另一台主机连接热点,加入游戏,观察Wireshark监听的封包情况:
在这里插入图片描述
当另一台手机加入游戏后,Wireshark并没有监听到什么可疑的封包,只是主机创建房间的消息一直在广播,之后我开始了游戏,房间内只有我的两部手机,手机A的角色移动也同步传输到了手机B,但是Wireshark中并没有从A到B的数据包(无论TCP还是UDP都没有),这曾经让我一度陷入困惑。

随后我又观察到,在游戏的过程中,不断能接收到ARP封包,在广播寻问手机A(192.168.137.110)、手机B(192.168.137.92)的物理地址。在这里插入图片描述
这说明,他们之中绝对有通信,只是Wireshark并未监听到。

问题分析过程:

出现了理论上应该存在、但是却监听不到的封包着实让我头疼。期初我的想法是,两个游戏角色的行为可以同步,说明他们之间绝对有数据往来,二者都连接到我电脑的热点上,按理说,我电脑虚拟wifi的网卡是二者数据往来的必经之路,只要在这里设下监听,什么数据都应该尽收眼底,所以我曾一度认为是软件配置和使用方法的问题,但我又能找到方法证明软件和配置都没有问题,那么问题出在哪里呢?我从中午思考这个问题一直到凌晨两点都未曾想通,要是这个问题解决不了,后面也无法继续了。

凌晨两点,我关了房间的灯,准备卧床睡觉,在床上我尽力回忆着计算机网络相关的理论知识,企图推出问题的原因,我想到了我的计网老师,我努力回想她上课讲过的每一句话……甘霖娘,我没去上几节课,上课也复习数学来着,仅剩的记忆也就是她最后一节课让我打扫实验室来着……

这事不怪老师,是我自己没去上课,虽然我没去上过课,但是书我还是看了,书中自有黄金屋,我又开始努力想,书上都写了什么?突然一句话映入我的脑海

我们知道适配器有过滤功能。但适配器从网络上每收到一个MAC帧就先用硬件检查MAC中的目的地址。如果是发往本站的帧则收下,然后再进行其他处理。否则就将此帧丢弃,不再进行其他处理。

​ ——《计算机网络》第七版 P95页 第四段

我清楚的记得这句话,上述引用是书中原文,这句话让我印象非常深刻,因为它有错别字!

但适配器从网络上每收到一个MAC帧就先用硬件检查MAC中的目的地址。

这句话的第一个字显然是错字,此处用”但”逻辑不通,应该“当”,作者打字的时候少打了个“g“。

目前的路由器兼有交换机的功能,加之监听到的数据包中有很多ARP协议,事件的全貌一下就理出来了:

  • 当手机B玩家加入游戏后,B得到了手机A的IP地址
  • B向A发送IP报,IP报在数据链路层封装成帧,通过ARP协议得到了IP对应的MAC地址
  • 当B发送出去的MAC帧传输到我的电脑时,我电脑负责交换机功能的那一部分硬件,直接将B发送的帧转发给了A,并没有向上传输
  • Wireshark监听我电脑负责路由的那一部分,B发送给A的MAC帧没到这一层,所以监听不到AB之间直接通信的数据报
混杂模式

按理说,开启混杂模式,应该就可以监听到MAC帧了,但是这里我并未成功,具体原因不明,先mark日后探究。

监听游戏进行阶段的封包数据(正确方法)

总之,进行到这一步,想获取游戏进行阶段的封包数据,只在网关监听是万万不行的了,必须想办法在安卓上直接对设备网卡进行监听。幸亏Android和Linux有着千丝万缕的联系,在安卓上可以直接执行shell,这才为在安卓上拦截封包提供了可行性。想实现封包的拦截需要有:

  1. 一台支持adb的、已经root的手机
  2. tcpdump工具

我使用的是逍遥安卓模拟器工作室版,在它根目录下有一个叫memuc.exe的工具,可以提供ADB支持,同时该模拟器默认就是已经ROOT的,很好满足了我的第一个需求。

按住Shift,右键点击根目录文件件空白处,选择在此处打开命令行窗口,键入一下指令

memuc.exe adb -i 0 shell

在这里插入图片描述
可对编号为0的虚拟机执行shell命令

在安卓机装入tcpdump并开启监听的方法可以参考:

https://www.cnblogs.com/likwo/archive/2012/09/06/2673944.html

搭建实验环境

为实现模拟安卓在局域网联机的环境,又需要如下两点:

  1. 模拟器多开,至少2台
  2. 模拟器连于同一路由下

第一点逍遥模拟器的多开管理器已经做到了,第二点需要稍微配置一下。在这里插入图片描述
找到设置-》网络设置,将网络模式设置为桥接,点击详细设置,IP设置为DHCP。在这里插入图片描述
两台虚拟机都这样设置,注意:逍遥模拟器只有工作室版有网络模式设置这个功能,个人版没有,所以特别注明是工作室版。

执行监听

进入shell模式

memuc.exe adb -i 0 shell

在shell模式下,输入:

tcpdump -n -v -w "/sdcard/capture.pcap" src host 192.168.137.82 or src host 192.168.137.217 

这里的在192.168.137.82 和192.168.137.217 是我两台模拟器的ip地址,可以在设置-》关于手机-》状态信息中查看到。

模拟器上完成创建游戏、加入游戏、行走、使用技能、退出游戏等操作。

在命令行中按ctrl+c退出,输入

memuc.exe adb -i 0 pull /sdcard/capture.pcap capture.pcap 

将capture.pcap文件从模拟器中下载出来,随后用Wireshark加载该文件,进行分析。在这里插入图片描述

封包分析

将刚才得到的封包数据,按时间进行排序,去掉无用的封包,从创建房间封包开始分析。在这里插入图片描述
如此我们可以推断出,创建房间的主机IP为192.168.137.217

随后收到的是来自 192.168.137.82:35198,发送给192.168.137.217:7777 的封包在这里插入图片描述
同时我们也看到, 192.168.137.217:7777 接收到封包后立刻给192.168.137.82:35198 回了一个。

追踪这个过程的UDP流,我合计,这应该就是我想要的,是游戏交互过程用于同步的数据报。在这里插入图片描述
有些数据报包含了武器、生命、能量等信息,应该是用于开局同步玩家信息用的,不过这数据报几乎就是明文……要是……岂不是……。

结语

如此,整个游戏局域网联机的具体实现流程就比较清晰了,元气骑士之间的通信用的全部都是UDP,其通信流程大体如下:

  1. 主机A创建游戏房间,将房间信息在局域网内23333端口广播,同时监听自己的7777端口
  2. 主机B接受到了A的广播信息,当B想加入A的时候,B就启用一个随机端口,向A地址的7777端口发送数据
  3. A的7777端口监听器,发现了B的数据,记录B的发送端口,并立刻向B的发送端口发送响应数据
  4. B给A发数据就发7777端口,A给B发送数据就往B第一个数据报的发送端口发,如此实现两个游戏的通信

房间信息在局域网内23333端口广播,同时监听自己的7777端口
2. 主机B接受到了A的广播信息,当B想加入A的时候,B就启用一个随机端口,向A地址的7777端口发送数据
3. A的7777端口监听器,发现了B的数据,记录B的发送端口,并立刻向B的发送端口发送响应数据
4. B给A发数据就发7777端口,A给B发送数据就往B第一个数据报的发送端口发,如此实现两个游戏的通信

要实现异地局域网联机,其实可以不用关心A给B发了什么,也不用关心B给A发了什么,只需要实现上述端口的监听与转发即可,现在已经迈出了第一步了,终于搞清楚转发哪些端口了,下一步就是得实现一个支持内网穿透的全双工转发机了,这涉及网络编程、多线程等知识,这才是真正头疼的地方,我慢慢更吧。

  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值