U3D 初窥网络通讯教程1


OK,编辑了两款单机游戏之后我们现在应该尝试一下网络通讯功能了。


一听到网络通讯功能大家有可能就会想到复杂的协议以及Socket编程,好吧Unity作为一个非常智能(傻瓜)的游戏编辑器,他自带了一个叫做NetWork的

类用于专门处理通讯交互。


虽然Unity自备了这一个类,但为了更好的理解和使用,在最初我们还是大致地了解一下网络编程。

学有余力的同学自行阅读,没有余力的同学请果断跳过。

——————————————————————————————————————————————————————————

网络编程

  • WinSock,主要基于socket来开发客户端和服务器端程序。(基于TCP/IP协议模型中各层之间的联系

  • WinInet,主要是用作开发客户端。基于TCP/IP中的应用层。

  • ISAPI,主要是开发基于浏览器刻画段和服务器程序,扩展了TCP/IP模型中的应用层。

  • CGI主要是开发基于浏览器客户端和服务器程序。基于应用层

网络编程基础知识 

 开源网络封装库 :
ACE,ICE,asio,cppsocket,netclass,poco,SimpleSocket,socketman,Sockets 

开源FTP 
FileZilla 

开源服务器 
Apache 

网游服务器开源框架 
GNE,HawkNL,RakNet,SDL_net

 

网络协议分析软件:

Sniffer工具

Wireshark 开源的经典的协议分析工具Wireshark, http://www.wireshark.org/

WPE -------抓包

Ethereal  -------协议分析 
SockMon5  -------抓包及错误分析

————————————————————————————————————————————————————————————


Unity的NetWork

虽然Unity自己有一个NetWork用于网络通讯,但不得不承认,最通用的网络编程还是Socket。毕竟Unity network只是为了方便,还是
会存在许许多多的限制。
NetWork比较适合短连接的游戏,也就是说他和网络不是实时连接通信的,用于局域网联机的话效果十分不错,但是如果上升到了MMO游戏,则不太适宜。
Socket则具备着相当高的自由度,主流游戏均采用它。但是它比较反,需要写 数据类型转化,数据->字节流->数据,稍有错误就会崩盘...

OK废话不多讲,下面我们直接进入实战阶段,使用一下Unity的NetWork。

打开Unity新建一个工程,和以往一样,在Project下新建若干个文件夹。

新建一个本机服务器

由于我们只需要简单的GUI图形界面,所以直接将脚本挂载到Camera上即可。
给Main Camera添加一个脚本,不妨叫做Server。

//首先定义一下端口
int Port = 2048

端口

这里大家有可能会有疑惑,什么是 端口?Port?

那众所周知,我们上网的时候,自己的电脑会被分配到一个IP地址,用来区分不同的主机。互联网上数据包的接受和发送都是根据目的主机的IP地址来进行路由选择的。
现在问题就来了,我们的电脑上有各种各样的软件,迅雷下载需要接收数据包,K播看视频需要接收数据包,腾讯聊天你也需要数据包,不同的数据包被发到同一个IP地址主机,怎么区分呢?这时候就需要Port/端口。  
操作系统为各个发出响应的进程分配了不同的队,通过网路发来的数据包按照端口被分配到相对应的队中,等待进程的使用。同理,当主机的程序需要发送数据包的时候,也需要打上相对应的端口。
更形象的来说,我们的主机就是一家银行,数据包就是我。我来到银行门口,调度员问我,先生你好,你需要什么服务呀?我说我要存款。他就说,先生请到3号窗口去排队吧!这里3号窗口就是一个端口。


有了端口之后,接下来就要根据端口状态来分配任务了。
可以再Unity的脚本帮助中查到,端口状态由NetWorkPeerType存储,一共有四种类型。

官方的实例代码已经很详尽了,我们在这里稍作改动
void OnGUI()
{
	switch(Network.PeerType)//根据不同的情况选择下一步行动
	{
		case NetworkPeerType.Disconnected:
		StartServer();//未连接状态下,开启服务器
		break;
		case NetworkPeerType.Connecting:
		GUILayout.Label("Connecting");//连接状态下显示已连接
		break;
		case NetworkPeerType.Server:
		onServer();//在服务器端口配置服务器
		break;
		case NetworkPeerType.Client:
		break;
	}
	
}

void StartServer()
{
	if(GUILayout.Button("create Server"))//如果按下开启服务器按钮
	{
		NetworkConnectionError e =Network.InitializeServer(12,Port,false);
		//获取初始化服务器端的状况
		Debug.Log("Error"+e);//输出调试日志
	}
}
——————————————————————————————————————————————————————————————
读者会发现,在按下了服务器按钮之后,调用了InitializeServer对服务器端进行初始化。
这个函数的三个参数分别为 允许最大的链接数量   ,端口号   ,是否启用NAT机制 (NetWork Address Transform网络地址转换——简单来说就是讲内网地址和私有地址转化成合法公有IP,是一个用于解决IP紧缺问题的手段)

细心地读者就会疑问为什么初始化会属于连接错误类呢?其实虽然这个类叫做错误类,但是它也有NoError的值。而且初始化失败了就是一种错误嘛。下面是所有NetWorkConnectionError的变量值


——————————————————————————————————————————————————————————————
void onServer()
{
	GUILayout("Server is waiting for Client");

	int length = Network.connections.Length;//获取当前客户端的连接数量
	for(int i=0;i<length;i++)
	{
		GUILayout.Label("Client"+i);
		GUILayout.Label("Client IP"+Network.connections[i].ipAddress);
		GUILayout.Label("Client Port"+Network.connections[i].port);
	}

	if(GUILayout.Button("Disconnected"))
	{
		Network.Disconnected();//按下即断开网络
		
	}
	
}

void Start()
{}


ctrl shift B导出,在这里我们选择网页版方便测试,保存为Server。运行一下

这样我们的简易服务器就建立完成了。接下来就要做一个客户端作为连接端口。

Client端

好的现在我们把MainCamera上的脚本取消挂载,弄一个新的脚本给他,叫做Client
那么Client的代码和Server一样,一开始也要做一个状态判别
void OnGUI()
{
	switch(Network.PeerType)//根据不同的情况选择下一步行动
	{
		case NetworkPeerType.Disconnected:
		StartConnect();//未连接状态下,启动客户端
		break;
		case NetworkPeerType.Connecting:
		GUILayout.Label("Connecting");//连接状态下显示已连接
		break;
		case NetworkPeerType.Server:
		break;
		case NetworkPeerType.Client:
		break;
	}
	
}
void StartClient()
{
<span style="white-space:pre">	</span>if(GUILayout.Button("Connect"))//如果按下开启客户端按钮
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>NetworkConnectionError e =Network.Connect("127.0.0.1",2048);
<span style="white-space:pre">		</span>//获取连接服务器端的状况
<span style="white-space:pre">		</span>Debug.Log("Error"+e);//输出调试日志
<span style="white-space:pre">	</span>}
}
可以看到我们的客户端逻辑其实和之前差不多,判别状态进行初始化,作为一个客户端,他的“初始化”就是连接服务器。
而这里Connect的两个参数为 IP和Port。
正如前文讲到的,数据包发送之后需要按照IP找到主机,根据Port找到进程。
127.0.0.1为本地主机的保留IP,不许要联网就是如此,使用过Putty,SSH连接单片机的同学应该理解。
而2048就是我们之前给服务器设定的端口。当然硬编码不太好,建议将这两个值声明为全局变量。

再次导出,运行
按下连接按钮。

成功连接了!有没有很兴奋!!= =虽然很low啦

今天的大概内容就到这里。
咱们明天见。
——————————————————————————————————————————————————————————————
笔者按,前些日子比较繁忙,博客进入了低产模式,现在开启Unity网络编程和新实例一个。希望大家多多关注。
本系列 大部分代码出自《Unity 3D 游戏开发》,作者宣雨松。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值