unity 5以后底层封装了一些network模块。比较有名的是unet 就是unityNetworkmanager,还是很强大的,用来做一些同步,联机小游戏还是很方便的,因为不需要我们自己再去搭建底层,只需挂载一些组件即可完成过同步。
研究unet的时候,意外发现另一套网络架构--networking。这个相比uent虽然需要我们自己去写更多脚本,但是相比之下,uent性能并不十分稳定,延迟也是比较高的。而networking更类似于我们自己对socket的封装,但是这些底层结构unity已经帮我们搭建,我们可以直接调用。不多说,结合例子开始讲解。
首先作为服务器端,我们可以直接打包,或者在unity上直接 开启服务器,更加直观不想之前只能做Windows窗口程序。
//协议类 数据结构
public class UserMsg : MessageBase
{
public string SenderIP;
public string message;
public string type;
}
public class NetworkingMgr
{
private static NetworkingMgr instance = null;
public static NetworkingMgr Instance
{
get
{
if (instance == null)
instance = new NetworkingMgr();
return instance;
}
}
public bool connected=false;
/// <summary>
/// 用户信息分类
/// </summary>
private const short userMsg = 64;
public string Ip; //服务器IP
/// <summary>
/// 获取本机IP
/// </summary>
/// <returns></returns>
private static string GetInternalIP()
{
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
{
localIP = ip.ToString();
break;
}
}
return localIP;
}
#region 服务器逻辑
//玩家连接个数
public int count = 0;
private List<NetworkConnection> clients = new List<NetworkConnection>();//记录客户端
/// <summary>
/// 启动
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
public void SeverStart(string ip ,int port)
{
if (!NetworkServer.active)
{
if (ip == "")
{
ip = GetInternalIP();//默认本机做服务器
}
if (port == 0)
port = 4455;
Ip = GetInternalIP ();
connected = NetworkServer.Listen(ip, port);
Debug.Log("服务器启动状态:" + connected);
if (connected)
ServerRegisterHandler();
}
else
Debug.Log("服务器已经开启");
}
/// <summary>
/// 服务器端注册事件
/// </summary>
private void ServerRegisterHandler()
{
NetworkServer.RegisterHandler(MsgType.Connect, OnServerConnected);
NetworkServer.RegisterHandler(MsgType.Disconnect, OnServerDisconnected);
NetworkServer.RegisterHandler(MsgType.Error, OnServerError);
NetworkServer.RegisterHandler(userMsg, ServerGet);//接受消息
}
//服务器接受到客户端信息
private void ServerGet(NetworkMessage netMsg)
{
UserMsg Msg = netMsg.ReadMessage<UserMsg>();
Debug.Log("收到客户端信息:" + Msg.message);
ServerSendAll(Msg);
//for (int i = 0; i < clients .Count ; i++)
//{
// SeverSendToClient(Msg, netMsg);
//}
}
//服务器错误事件
private void OnServerError(NetworkMessage netMsg)
{
}
//有客户端断开事件
private void OnServerDisconnected(NetworkMessage netMsg)
{
count--;
clients.Remove(netMsg.conn);
UserMsg msg = new UserMsg()
{
message = "掉线!",
SenderIP = netMsg.conn.address,
type = "OutLine",
};
ServerSendAll(msg);
}
// 有客户端登入时调用
private void OnServerConnected(NetworkMessage msg)
{
count++;
clients.Add(msg.conn);
Debug.Log("玩家登入:" + msg.conn .address);
}
//服务器广播
public void ServerSendAll(UserMsg um)
{
if (NetworkServer.active)
{
if (NetworkServer.SendToAll(userMsg, um))
{
Debug.Log("Server send:" + um.message);
}
}
}
//发送给指定客户端
public void SeverSendToClient(UserMsg um, NetworkMessage netMes)
{
if (NetworkServer.active)
{
Debug.Log("向客户端发送数据:" + um.message + " ---- " + DateTime.Now);
NetworkServer.SendToClient(netMes.conn .connectionId , userMsg, um);
}
}
//停止服务器
public void ShutdownServer()
{
if (NetworkServer.active)
{
ServerUnregisterHandler();
NetworkServer.DisconnectAll();
NetworkServer.Shutdown();
if (!NetworkServer.active)
{
Debug.Log("shut down server");
}
}
}
//服务器注销事件
private void ServerUnregisterHandler()
{
NetworkServer.UnregisterHandler(MsgType.Connect);
NetworkServer.UnregisterHandler(MsgType.Disconnect);
NetworkServer.UnregisterHandler(MsgType.Error);
NetworkServer.UnregisterHandler(userMsg);
}
#endregion
}
以上只是一个简单是服务器端,当然,如果你想要更可视化,可以自己做些酷炫界面的。
然后是客户端
public class NetworkingMgr
{
private static NetworkingMgr instance = null;
public static NetworkingMgr Instance
{
get
{
if (instance == null)
instance = new NetworkingMgr();
return instance;
}
}
public bool connected=false;
/// <summary>
/// 用户信息分类
/// </summary>
private const short userMsg = 64;
public NetworkClient myClient;//本机客户端
/// <summary>
/// 做客户端 连接服务器
/// </summary>
/// <param name="ip"></param>
/// <param name="port"></param>
public void Connected(string ip, int port,Action callback)
{
if (ip == "")
{
ip = GetInternalIP();
}
if (port == 0)
port = 4455;
myClient = new NetworkClient();
myClient.Connect(ip, port);
myClient.RegisterHandler(MsgType.Connect, (netMsg) =>
{
Ip = GetInternalIP ();
connected = myClient.isConnected;
Debug.Log("连接成功!!!");
if (callback != null)
callback.Invoke();
});
}
//向服务器发送信息
public void ClientSend(UserMsg um)
{
if (myClient.isConnected)
{
um.SenderIP = Ip;
if (myClient.Send(userMsg, um))
{
Debug.Log("发送成功!!");
}
}
}
// 客户端注册事件
public void ClientRegisterHandler()
{
connected = true;
//myClient.RegisterHandler(MsgType.Connect, OnClientConnected);
myClient.RegisterHandler(MsgType.Disconnect, OnClientDisconnected);
myClient.RegisterHandler(MsgType.Error, OnClientError);
//myClient.RegisterHandler(userMsg, ClientGet);
}
//客户端接受到服务器信息
//private void ClientGet(NetworkMessage netMsg)
//{
// UserMsg Msg = netMsg.ReadMessage<UserMsg>();
// Debug.Log("收到服务器信息:"+Msg.message);
//}
//客户端错误事件
private void OnClientError(NetworkMessage netMsg)
{
}
//客户端冲服务器断开事件
private void OnClientDisconnected(NetworkMessage netMsg)
{
}
//客户端连接到服务器事件
//private void OnClientConnected(NetworkMessage netMsg)
//{
// connected = myClient.isConnected;
// Debug.Log("连接成功!!!");
//}
// 停止客户端
public void ShutdownClient()
{
if (myClient.isConnected)
{
ClientUnregisterHandler();
myClient.Disconnect();
//NetworkClient.Shutdown()使用后,无法再次连接。
//This should be done when a client is no longer going to be used.
//myClient.Shutdown ();
}
}
// 客户端注销事件
private void ClientUnregisterHandler()
{
myClient.UnregisterHandler(MsgType.Connect);
myClient.UnregisterHandler(MsgType.Disconnect);
myClient.UnregisterHandler(MsgType.Error);
myClient.UnregisterHandler(userMsg);
}
这些方法接口都是unity封装完成开放的,直接调用就行,启动一个服务器,一个客户端,测试,通过!!
若有问题欢迎咨询指正!!!.
demo下载地址:https://download.csdn.net/download/nt_xs_j/10502072