用unity3d实现简单的主服务器连接

时间:2022-11-07 17:55:25

unity3d实现简单的主服务器连接

参考自鹰大的网络实例

-------------------------------------------------华丽的分割线-------------------------------------------

一. UI以及主逻辑

//值得注意的是

//1Network.useNat已经不再使用 直接用一个变量替代它

//2GUILayout.BeginScrollView()有更好的重载函数来使用

//3Network.InitializeServer(players, port);也已经过时

//4.测试部分有些函数也已经过时,可以参考圣典做修改

//5.似乎有连不上主服务器的问题

主逻辑函数

1.Awake()

l 初始化服务器ipport

l 初始化窗口

l 初始化游戏模式[可选]

2.OnGUI()

l 检测是否有连接到服务器或成为服务器【开始时至少是正在连接了】

n 有的话加载场景

n 若没有 有两种可能:出错了,尚未开始连接[分类处理]

u 若出错 弹出窗口提示错误

u 此时一定是还没连接 可以做快速游戏或者玩家自定义加入两种

l 若玩家点击了快速游戏 【还没有开始游戏】

n 调用快速游戏函数

l 若玩家点击了自定义游戏

n 可以创建多种方式让玩家登入[此时设计3种:)]

u 根据房间列表加入

u 根据服务器ip[可以替换成建立服务器的玩家名称等等]

u 自己创建一个游戏

n 玩家可以选择退回到主菜单

l 若玩家还没有点选此时[应该设计选择UI]

n 输入玩家姓名

n 创建快速游戏或自定义游戏

实现函数

1) playNowFunction()快速游戏

l 可以选择在加载的时候退出游戏

l 如果尝试足够多次连接主机都没有成功 自己作为服务器创建一个主机[创建房间]

l 调用具体处理快速游戏的脚本开启游戏

n 如果快速游戏返回失败 玩家自己创建一个主机[创建房间]

n 否则 此时系统正在尝试快速游戏,显示处理进展[比如倒计时]

以下3个均为窗口回调函数[创建一个适于交互的UI然后加入游戏]

2) hostGUI()自己一个创建游戏

l 创建窗口要求玩家输入创建房间的必要信息[使用的端口 玩家数目]

l 确认信息后创建房间

3) directConnectGUIWindow()通过ip加入游戏

l 正在连接时 显示消息通知玩家正在连接

l 否则 此时尚未输入信息 `

n 玩家输入目标房间信息[ip port  是否useNat]

n 尝试连接该目标房间

4) listGUI()房间列表

l 创建滚动条[读取显示主机列表中主机的信息]

l 玩家可主动刷新房间列表[可选]

l 若列表中没有主机 显式向玩家说明

二.多人游戏具体实现

主逻辑函数[主要处理连接出现的问题]

1. Awake()

l 主机列表 new空间

l 连接测试

l 判断并说明本机ip类型[公有or私有]

l 修改主服务器信息[可选]

2. Start() start中可做协同操作

l 请求主机列表

3. Update()

l 测试Nat

网络连接函数

1) OnFailedToConnectToMasterServer(info: NetworkConnectionError)  木有连接到主服务器

l 本例中木有提供解决方法

2) OnFailedToConnect(info: NetworkConnectionError) 连接服务器失败

l 调用连接失败处理函数

3) Connect(ip : String, port : int, usenat : boolean) 连接函数[感觉不是很必要]

似乎只在连接失败处理重试时调用 【封装价值不清楚】

l 根据参数连接服务器

l 标识当前正在连接中

4) OnConnectedToServer() 客户端成功连接到服务器后调用

l 标识暂停网络功能的使用 因为在客户端还在加载的时候,我们要防止从游戏局内发出一些无法识别的网络信息

l 保存服务器的ipport到偏好[便于以后的使用]

实现具体功能的调用函数

1.FailedConnRetry(info: NetworkConnectionError) 针对连接失败的各种情况进行处理

l 当登入服务器密码输入有误 此时标识不再重试

l 当标识当前客户端正在尝试连接当前服务器时[有根据主机调用过connect 系统会假定此时仍可以再次连接本服务器]

l 若可以重试并且useNat==true并且当前尝试的主机要求NAT穿透 我们此时就不用NAT穿透再连接一次当前服务器  此处应该忘了对ip记录存储

l 否则当前的服务器已经不能再连接了  将useNat重置、尝试过的服务器+1、标识当前没有正在连接服务器

l 当标识当前客户端没有正在尝试连接当前服务器时【即没有使用快速游戏开始游戏】//没理解透

l 由于本例没有对非快速游戏的连接做操作 先标识连接消息为” Failed to connect!”

l 【似乎走不到这一步。。。】当服务器要求useNat并且客户端也使用了useNat连接时 不用useNat再尝试一次【不能穿透也有可能连接的 比如没有私有ip的联网公有ip

l 否则连接一定失败了 

根据连接失败原因不同传出不同的失败提示、重置port、重置useNat为测试后的正式结果【当前客户端的实际状况】

2.TestConnection() 测试Nat 针对正在连接的轮询测试连接 对结果进行反馈操作 1. 测试结果为ConnectionTesterStatus.Error

说明出现未知问题,可能是没有可用的网络连接 标识完成Nat测试

2.  ConnectionTesterStatus.Undetermined:

说明尚未测试完成 标识未完成Nat测试

3.  ConnectionTesterStatus.PrivateIPNoNATPunchthrough 私有ip、不能做Nat穿透

此时要过滤使用了Nat穿透的客户端 此时只能做局域网游戏 标识过滤Nat主机,完成测试,useNat=true【此处不理解 不是应该不用穿透么???但没出现这个问题不知道具体情况如何 遇到的朋友帮忙看一下】

4.  ConnectionTesterStatus.PrivateIPHasNATPunchThrough 私有ip、能做Nat穿透

若是检测正在探测公有ip,说明公有ip地址不能连接[被端口阻塞]

【若是服务器,在开启的情况下NAT穿透已经是启用的了;若是客户端,在主机请求时,开启】

不论能否检测到公有ip,都将useNat=true,标识完成NAT测试

5. ConnectionTesterStatus.PublicIPIsConnectable

可以直接连接公有ip地址,标记useNat=false、标识完成NAT测试

6. ConnectionTesterStatus.PublicIPNoServerStarted  公有ip被阻塞

a) 若是不是正在探测公有ip,说明可以绕过防火墙  强制测试NAT连接、标记正在探测公有ip、设计一段时间

b) 若一段时间后依旧阻塞,重置探测公有ip[false]useNat=false、标记完成NAT测试

7. 其他情况 出现错误

最后将当前的useNat标记为正式的Nat状态

如果测试完成 将测试情况输出便于检查错误

对外的调用接口

l StartHost(players : int, port : int) 创建服务器 对服务器初始化封装

l 若玩家填入小于修改至少为1[保证至少服务器有一个玩家]

l 初始化服务器

l PlayNow(timeStarted : float ) 快速游戏 通过访问游戏列表尝试连接所有的游戏

l 遍历主机列表 寻找没有设定密码、过滤穿透且主机没有穿透或者使用穿透且没有过滤的主机【不能穿透就不去穿透】【有一类是不能做穿透的】 找到作标记

l 若连接服务器的玩家没有超过限制

l 并且正在尝试连接快速游戏【感觉这里有问题 连接太久就得让人下线么???】

l 若连接了太长时间  由定时器中断

连接重试

l 如果当前没有正在尝试连接主机 且正在的尝试主机小于当前轮询的主机的编号

l 标记正在尝试连接快速游戏 正在尝试的主机编号设为当前编号 标记最后连接的主机的useNat和本客户端的useNat属性与服务器一致 连接该服务器 标记最后连接快速连接的时间为当前时间

l 对主机列表做冒泡排序[目的是让人员较少的房间增大被快速游戏加入的概率 减少等待]

·FetchHostList(manual : boolean)  //请求主机限制[更新主机列表]   自动每隔2分请求一次 主动每隔5秒请求一次

三.游戏加载完成后 处理连接、掉线、状态

类的主逻辑

1.Awake()

允许网络信息传递

若是服务器,应该在主服务器注册游戏

2.OnGUI() 轮询处理当前的连接状况

Network.peerType == NetworkPeerType.Disconnected 已断开

Network.peerType == NetworkPeerType.Connecting 正在尝试连接

Network.peerType == NetworkPeerType.Client 当前端是客户端

Network.peerType == NetworkPeerType.Server 当前端是服务器

可以选择断开

连接、断开处理

客户端:

1.OnDisconnectedFromServer(info : NetworkDisconnection) 从服务器断开

服务器:

1.OnPlayerConnected(player: NetworkPlayer) 服务器侦测到客户端连接到服务器

2.OnPlayerDisconnected(player: NetworkPlayer) 服务器侦测到客户端从服务器断开