不用浩方互联网打魔兽争霸全攻略
魔兽建立连接分析
1 udp获得游戏列表(A是主,B是客户机)
B进入游戏,进入局域网,会向局域网发出udp广播,udp目标端口是6112,A收到这个广播后返回一个udp包给B,B才会在魔兽的游戏列表里看到A建的游戏。
2 看到A建的游戏后,B双击进入游戏会建立一个到A的tcp连接,端口也是6112 。
游戏方案
1利用使用ddwrt的路由器的pptp转发功能实现。
我之前没有测试成功,可能是版本的问题,现在测试的ddwrt是DD-WRT v24-sp2 (01/01/09) mini-usb-ftp (用std 还是mini 都可以) (SVN revision 11296M VINT Eko)。
进入ddwrt 管理界面,service > vpn 打开pptp服务设置用户密码,打开 Broadcast support(这个是启用bcrelay模块,负责转发广播包) 选项。
客户端拨号到路由器连接vpn,到此就和在同一网段的局域网打游戏一样了。(魔兽争霸已经测试成功)
其他局域网的游戏应该也可以比如cs,大家可以测试一下。不过基于ipx协议的局域网游戏可能不行。
2 普通vpn + battleLan
对于没有广播转发功能的vpn可以采用下面小程序。
battlelan(一个夸网段玩局域网游戏的程序) 下载 http://home.comcast.net/~sonicsmart/battlelan.html
(魔兽争霸已经测试成功)
3 只用battleLan
对于俩个adsl拨号的玩家,只使用battlelan填入主机adsl分配的公网ip就可以连接,而在宽带路由器后面的用户可以在路由器设置udp和tcp 6112端口的转发到你的机器。(魔兽争霸已经测试成功)
以上只是描述关键部分,至于ddsn的设置,vpn的设置,路由器的设置,battlelan的设置没有详细说明。
下面是在一个论坛看的BattleLAN工作原理:
--------------------------------------------------------
冰封抓包结果如下:
1》开游戏,点“局域网”发出消息:
172.16.28.16——>255.255.255.255 udp LEN=udp 24B 端口:6112——>6112
发送的数据:
f7 2f 10 00 50 58 33 57 14 00 00 00 00 00 00 00
2》开BattleLAN不发送消息
3》开BattleLAN点“局域网”发出消息172.16.28.16——>255.255.255.255 udp LEN=24 端口:6112——>6112
172.16.28.16——>BattleLAN中地址 udp LEN=24 端口:6112——>6112
其中发往172.16.30.35的消息为::(172.16.30.35是BattleLAN.ini中IP之一)
f7 2f 10 00 50 58 33 57 14 00 00 00 00 00 00 00
4》用BattleLAN正常非同子网联机过程:
172.16.30.30创建游戏,172.16.28.14进行正常连接过程:(172.16.28.14开BattleLAN)
172.16.28.14——>172.16.30.30 udp LEN=24 端口:6112——>6112
内容:f7 2f 10 00 50 58 33 57 14 00 00 00 00 00 00 00
172.16.30.30——>172.16.28.14 udp LEN=159 端口:6112——>6112
内 容:f7 30 97 00 50 58 33 57 14 00 00 00 01 00 00 00 d7 ca ab 02 e5 bd 93 e5 9c b0 e5 b1 80 e5 9f 9f e7 bd 91 e5 86 85 e7 9a 84 e6 b8 b8 e6 88 8f 20 28 79 6c 00 00 01 03 49 07 01 01 75 01 a1 75 01 db e9 23 03 4d cb 61 71 73 5d 45 6f 77 19 6f 6d 6f 61 65 5d 45 2b 6f 75 41 21 41 6d 6d 2b 73 75 61 73 73 21 77 d9 37 2f 35 31 21 41 49 65 21 43 4f 2f 77 33 79 35 01 79 6d 77 71 75 79 01 01 01 00 0a 00 00 00 01 00 00 00 01 00 00 00 0a 00 00 00 72 08 00 00 e0 17
(到此172.16.28.14看到172.16.30.30建的组,双击建的组进入到游戏中)
172.16.28.14——>172.16.30.30 tcp LEN=0 端口:3704——>6112
172.16.30.30——>172.16.28.14 tcp LEN=0 端口:6112——>3704
...
结论:
1》BattleLAN只做两件工作:1截本地到广播的包2将截到的包发往BattleLAN.ini中记录的IP
2》冰封联机原理:A建游戏,B去联,B只需向A发送一个LEN=24,源和目的端口为6112的特定UDP包就可以了。
这样我们可以通过原始套接字完成以上功能,利用此原理,我写了一个功能类似BattleLAN的软件(SendWar)可以正常连冰封。以下是其核心代码和步骤:
构造要发的包
char buffer[4096]="\x17\xe0\x17\xe0\x00\x18\x00\x00\xf7\x2f\x10\x00\x50\x58\x33\x57\x14\x00\x00\x00\x00\x00\x00\x00";//1.20版本
char buffer1[4096]="\x17\xe0\x17\xe0\x00\x18\x00\x00\xf7\x2f\x10\x00\x50\x58 \x33\x57\x15\x00\x00\x00\x00\x00\x00\x00";//1.21版本
初始化原始套接字
SendSocket = socket(PF_INET,SOCK_RAW,IPPROTO_UDP);
获取目的主机名(建游戏的主机名)
if(atoi(allIPstr[j])) //allIPstr[j]中记录的是目的主机字符串之一
{
u_long ip = inet_addr(allIPstr[j]);
hostdata = gethostbyaddr((char*)&ip,sizeof(ip),PF_INET);
}
else
{
hostdata = gethostbyname(allIPstr[j]);
}
if(!hostdata)
{
fflush(0);
continue;
}
sockaddr_in dest;
dest.sin_family = PF_INET;
dest.sin_addr = *(in_addr*)(hostdata->h_addr_list[0]);
//发包
sendto(SendSocket,buffer,24,0,(sockaddr *)&dest,sizeof(sockaddr_in));
sendto(SendSocket,buffer1,24,0,(sockaddr *)&dest,sizeof(sockaddr_in));
如目的主机确实有建游戏则发完包后可以看到所建的游戏,这样双击就可以进行游戏了
注意冰封1.21与1.20版本所发送的LEN=24UDP消息有稍微不同,所以上面发了两个包(BattleLAN与此不同,它是截获消息发送出 去,当然你也可认像BattleLAN一样,另外我没有计算较验码(不影响连游戏),我写的SendWar可以像BattleLAN一样工作(一直开着也 不会卡,当然没必要一直开)。
懂得了原理你也可以写出自己的BattleLAN了哦!