2024年1月11日发(作者:)

南航校内战网(对战平台)组建技术文档

2008年11月2日,校内战网(也叫对战平台)开始运行。一个星期不到,我们的QQ群爆满。经过一个星期的测试,我对下一步计划产生了若干种想法。遗憾的是,我不能再继续开发下去。但是我终归不希望这个计划就此流产,所以公开全部技术文档,期望有人继续下去。

关于我的身份,二院硕二的研究生,本科亦在南航,仅此而已。南航一直缺乏一个很好的交流平台,我希望能够有一些人留在这里和我讨论技术和音乐。

一、南航的网路结构

南航的网络结构相当复杂,而且存在诸多不合理的地方。今天找了很多同学来测试,得到一个大致的结果。

测试采用 Windows 自带的tracert命令,统一 trace 学校的 DNS 服务器得到的结果。箭头表示数据请求的方向。

注意到本科生的路由都是单向的,说明路由禁止内部通信,于是本科生之间的通信必须靠外部的服务器来交换数据。举个例子吧,当我们用QQ传递文件的时候,如果QQ认定两台计算机是同一局域网内的计算机,就启用点对点的传输协议。如果两台计算机不在同一局域网,则通过服务器转发。所以,我们应该注意到这样的现象:

1. 两台计算机都在研究生宿舍,文件传输速度等于局域网速度,大约 8M/s

2. 两台计算机都在本科生宿舍,文件传输速度等于服务器转发速度,大约 60K/s (数量级远小于第一种情况)

3. 两台计算机分别在研究生和本科生宿舍,文件传输等于服务器转发宿舍,同上

实际上,当我在研究生宿舍建立一个WEB服务器的时候,让本科生下载,速度达到 2M/s。而本科生建立 WEB服务器,研究生是不能访问的。

这就是我要说的学校网络不合理的地方。大家知道QQ的用户有多少,估计 90%的南航学生每人有一个帐号是合适的。由于本科生宿舍计算机通信必须通过外部服务器转发,在发送文件的时候,实际上占用了南航总带宽的双倍。就是说,当一个本科生向研究生传输文件的的速率是 60K/s 时,一去一回,实际上占用学校总带宽 120K/s。南航人这么多,你可以设想一下占用了多少带宽。而一旦南航取消本科生的数据传输限制,这个带宽就大大节约出来。我初步估计,南航总带宽至少30% 因为禁止本科生宿舍计算机相互通讯而浪费。南航是1000M的网络总带宽,其中300M被浪费了。

南航网络另一个不合理的地方是,所有WEB链接采用直接连接。而实际上,由于学校的访问数量太大,所有的WEB链接都应该采用缓存代理的方式连接。所谓缓存代理,就像是IE的缓存一样,只是把一个区域的所有计算机需要的文件统一缓存到指定的几个电脑而已。大家都知道IE缓存可以在下次访问时候加快速度,缓存代理是一个道理。我估计,南

航在这一部分浪费的带宽至少50%,也就是500M。

关于缓存代理的技术,我的其他文章有提到,这里不加赘述。

至于带宽的浪费,不仅浪费的是带宽,同时浪费的是电费和效率。

最有用的结论是,我们的游戏服务器建立在校园内部,不占用学校的总带宽。同时,由于一部分人使用校内战网而不使用VS等校外战网,可以为学校节省出很大一部分带宽。

二、对战平台服务器原理

游戏服务器采用GNU认可的开放源码软件,PvPGN。

基于BN的战网,其数据处理服务器并不是PvPGN本身,而是建立游戏主机的电脑。所以,这里要提出两个服务器的概念。一是PvPGN,二是建立主机的电脑。我们分别称之为列表服务器(简称服务器)和游戏服务器。PvPGN的作用仅仅是提供一个地址列表,并不提供游戏数据的转发。

客户端计算机『A』可以通过6112端口与服务器通讯,告知服务器『A』上线了,并将自己的IP和MAC地址告诉服务器。当客户端端『A』建立游戏主机之后,『A』给服务器一个请求,声明『A』建立了一个游戏主机。另一个客户端『B』在服务器上得到消息,就根据服务器提供的『A』的地址与『A』进行链接。游戏开始之后,『A』给服务器发一个消息,声明『A』已经开始游戏。而『B』在游戏开始之后向服务器发一个消息,声明自己已经开始游戏,然后只与『A』交换数据。游戏结束之后,『A』将游戏结果发给服务器,以便服务器统计排名。

下载PvPGN服务器

地址 /project/?group_id=2291

三、子服务器原理

前天的测评报告使用端口映射工具做子服务器,这是方案一。之后我又思考,得到方案二。

方案一

子服务器是一个端口映射工具,不提供列表功能,只提供数据转发。子服务器接受任何计算机来自6112端口的请求,将这个请求转发给服务器。由于端口映射的数据请求也是单向的,因而通过子服务器连接服务器的电脑不能建立游戏主机。由于子服务器自身的请求也被转发,因此自己不能建立游戏主机。

下载端口映射工具

地址 /soft/

方案二

子服务是一个代理服务器,提供标准SOCK5代理。客户端通过代理服务器链接服务器。此时,通过子服务器连接服务器的计算机仍然不能建立游戏主机,但是子服务器本身可以建立游戏主机。比方案一麻烦的是,由于客户端的Loader不能设定代理,需要通过第三方软件来设定强制代理。这个软件是ProxyCap,下载和使用参见相关教程。当然,我们可以将这个过程写到客户端里,这样就可以省掉这个麻烦了。

下载代理服务器

地址 /soft/

ProxyCap的下载和使用

地址 /bbs/?tid=2577&fromuid=1

动态域名

子服务主要建立在研究生宿舍的计算机上,也可能是放在不同宿舍的ARM9。但是研究生宿舍的计算机的IP是随机分配的,所以需要使用动态域名。这样,客户端可以通过域名来找到服务器。动态域名采用每步公司提供的免费服务,它可以将指定域名解析为内网或者最高网关的IP。当然,这里是要解析为内网,也就是本机网卡的IP。

通过Sniffer 监控,发现每步的协议很简单,只要客户端向服务器发送一个UDP数据包就可以了。

动态域名参考资料

地址

四、一些参数

这里提供测试期间得到的一些参数,这对于你继续开发会非常有用。

1. 服务器(ARM9)的功率,12Vx1.5A=18W(一个台式电脑的功率大约500W)

2. 一个客户端的带宽,小于等于500bps(电话拨号上网是56,000bps)

上面两个参数很重要,一是服务器功率很小,50小时消耗不到一度电,24小时开机,一个月不到14度,就是7块钱。二是一个客户占用带宽不到1K,所以我们可以限制每个客户使用的带宽是1K,同时限制代理使用的端口是游戏必须的端口,这样可以防止有人用这个代理登录QQ等。另一方面,即使登录1000个客户端,占用带宽不超出1M,而我们的网卡是10/100M自适应的,实际上都是100M的。

五、数据库

目前,游戏的帐号和代理的帐号是分开。我们可以考虑统一,或者允许一个登录帐号,以及若干不同的昵称。登录帐号使用学号,这个帐号用来和代理服务器连接。帐号写入远程或者本地的SQL数据库,可以通过WEB读取。于是我们实现了这样的功能,通过网络注册,

在网上实现排名功能。

六、下一步开发计划

以上的方案已经到了极致,但是有个很大的问题:江宁的同学不能建立主机!

我考虑了一个新的方案,建立VPN。VPN,VirturePrivite Network,即虚拟专有网络。VPN的建立,依然采用GNU认可的开放源码软件,OpenVPN。服务器上除了运行PvPGN,同时运行一个OpenVPN。当然,我们也可以采用两台服务器分散压力。即一台服务器专门用作OpenVPN,PvPGN作为成员之一加入。

客户端可以仿照VS等,除了连接服务器,另一个作用是指定启动游戏的时候将游戏数据传递到虚拟专有网络。而其他程序的数据则依旧使用原有网络。

下载OpenVPN

地址 /

七、可行性分析

刚开始搞战网的时候,隔壁宿舍一个同学反问我,现在VS、浩方、QQ等这么多平台,我高校内战网有什么意义。其实很简单,既然浩方搞了对战平台,VS还有有什么意义?关键所在,有需求就有市场。

八、遗憾的结局

虽然方向很明确,可是很遗憾,我没有时间和精力继续下去了。如本文开头所述,希望有人继续下去。

现有的服务器会一直运行下去,直到我毕业或者其他原因而不能继续。

感谢诸位支持校内战网的同学们!感谢诸多参与测试的同学们!

下面以cs1.6为例做下讲解。

1、D:HLServer开启一个真服,使用27015端口,确保外网列表里能够刷出,外网玩家能够进入。

(建议使用点通发布的【4554】HLDS服务端,下载地址参考以下网页:/forum/)

2、D:HLServer1开启一个假服,使用27016端口,挂在浩方或者QQ对战平台,挂上转服插件,比如“”,插件源码提供给你:

#include

#define MAX_SERVERS 4

#define MAX_SERVER_STRING 33

newnumServers = 0

newserverList[MAX_SERVERS][MAX_SERVER_STRING]

newserverMax = MAX_SERVERS

public redirect()

{

if (read_argc() != 2)

{

server_print("Usage: amx_redirect")

return PLUGIN_HANDLED

}

else if ((numServers + 1) >serverMax)

{

server_print("[AMXX] Max Number of Redirect Servers Reached.")

return PLUGIN_HANDLED

}

else

{

newcurrServer[MAX_SERVER_STRING]

read_argv(1,currServer,MAX_SERVER_STRING)

/* Check for dups. */

for(new i = 0; i

{

if(equal(currServer,serverList))

{

server_print("[AMXX] Redirect Server %s already exists!",currServer)

return PLUGIN_HANDLED

}

}

copy(serverList[numServers],MAX_SERVER_STRING,currServer)

server_print("[AMXX] Redirect Server added: %s",serverList[numServers])

numServers++

return PLUGIN_HANDLED

}

return PLUGIN_HANDLED

}

publicredirect_reload()

{

numServers = 0

server_print("[AMXX] Reloading Server Redirect List")

server_cmd("exec addons/amxmodx/configs/")

return PLUGIN_HANDLED

}

redirect_client(id,randomServer){

client_cmd(id,"echo ^"Server is currently full^"")

client_cmd(id,"echo ^"Redirecting

to %s^";wait;wait;connect %s",serverList[randomServer],serverList[randomServer])

}

publicclient_connect(id){

newmaxplayers

new reserved

newslotsfree

newreserveType

if(numServers> 0)

{

newrandomServer

if(numServers> 1)

randomServer = random_num(0,numServers-1)

else

randomServer = 0

if(cvar_exists("amx_reserved_slots"))

reserved = get_cvar_num("amx_reserved_slots")

else

reserved = 0

if(cvar_exists("amx_reservation"))

reserveType = get_cvar_num("amx_reservation")

else

reserveType = 0

maxplayers = get_maxplayers()

new players = get_playersnum() + 1 /* on connection we must add you */

slotsfree = maxplayers - players

//if ( ((slotsfree<= 0) || (slotsfree<= reserved)) && ((reserveType == 0) || (reserveType ==

3)) )

if ( (reserveType == 0) || (reserveType == 3) )

{

if(slotsfree<= 0)

redirect_client(id,randomServer)

else if((slotsfree<= reserved) && (!(get_user_flags(id) & ADMIN_RESERVATION)))

{

redirect_client(id,randomServer)

return PLUGIN_HANDLED

}

}

else if( ((reserveType == 1) || (reserveType == 2)) )

{

if( !(get_user_flags(id) & ADMIN_RESERVATION) )

{

if(slotsfree<= 0 )

{

redirect_client(id,randomServer)

return PLUGIN_HANDLED

}

}

}

}

return PLUGIN_CONTINUE

}

publicplugin_init()

{

register_cvar("KEEG_Redirect", "0.3.2",FCVAR_SERVER)

register_plugin("AMX Redirect","0.3.2","Namralkeeg")

register_srvcmd("amx_redirect", "redirect")

register_srvcmd("amx_redirect_reload","redirect_reload")

server_cmd("exec addons/amxmodx/configs/")

return PLUGIN_CONTINUE

}

3、在D:HLServer1cstrikeaddonsamxmodxconfigs里新建一个文件为,里面写上你的真服的ip,比如:amx_redirect "58.214.240.130:27015"。

4、如果想获取更佳效果,请在服务器中开启机器人插件,通过服务器预留通道转人,也就是说你建24人的假服,就在里面加入23个机器人,新进的第24个玩家就会转到你的真服里。

5、如你所说,如果想让局域网的玩家也能玩,就不需要添加机器人了,你建的平台服人满后会自动转人到你的真服、也就是你的公网服的。

以上答复是否具有指导性,对你是否有用。

如果有什么疑问,加群36189378,找我或者其它有经验的人提问。