using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Collections.Generic;
using System;
using System.IO;
//實時消息處理委托
public delegate void NetEventHandler (string msg);
public class NetUtility
{
//單例
public static readonly NetUtility Instance = new NetUtility ();
//消息回調(diào)
private NetEventHandler ReceiveCallback;
//服務(wù)器Tcp
private TcpListener tcpServer;
//客戶端Tcp
private TcpClient tcpClient;
//緩沖區(qū)
private byte[] buffer;
//緩存數(shù)據(jù)組
private List<byte> cache;
//網(wǎng)絡(luò)節(jié)點
private IPEndPoint serverIPEndPoint;
/// <summary>
/// 設(shè)置網(wǎng)絡(luò)節(jié)點
/// </summary>
/// <param name="ep">網(wǎng)絡(luò)節(jié)點.</param>
public void SetIpAddressAndPort (IPEndPoint ep)
{
//只寫網(wǎng)絡(luò)節(jié)點
serverIPEndPoint = ep;
}
//設(shè)置委托
/// <param name="handler">消息委托.</param>
public void SetDelegate (NetEventHandler handler)
{
//只寫賦值回調(diào)
ReceiveCallback = handler;
}
/// <summary>
/// Initializes a new instance of the <see cref="NetUtility"/> class.
/// </summary>
private NetUtility ()
{
//服務(wù)器實例
tcpServer = new TcpListener (IPAddress.Any, 23456);
//客戶端實例
tcpClient = new TcpClient (AddressFamily.InterNetwork);
//緩沖區(qū)初始化
buffer = new byte[1024];
//緩存數(shù)據(jù)組實例
cache = new List<byte> ();
//默認網(wǎng)絡(luò)節(jié)點
serverIPEndPoint = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 23456);
}
#region Server Part:
/// <summary>
/// 開啟服務(wù)器
/// </summary>
public void ServerStart ()
{
//開啟服務(wù)器
tcpServer.Start (10);
//服務(wù)器開啟提示
ReceiveCallback ("Server Has Init!");
//開始異步接受客戶端的連接請求
tcpServer.BeginAcceptTcpClient (AsyncAccept, null);
}
/// <summary>
/// 異步連接回調(diào)
/// </summary>
/// <param name="ar">Ar.</param>
void AsyncAccept (System.IAsyncResult ar)
{
//接受到客戶端的異步連接請求
tcpClient = tcpServer.EndAcceptTcpClient (ar);
//有新的客戶端連接提示
ReceiveCallback ("Accept Client :" + tcpClient.Client.RemoteEndPoint.ToString ());
//異步接收消息
tcpClient.Client.BeginReceive (buffer, 0, 1024, SocketFlags.None, AsyncReceive, tcpClient.Client);
//異步接受客戶端請求尾遞歸
tcpServer.BeginAcceptTcpClient (AsyncAccept, null);
}
/// <summary>
/// 異步接收消息回調(diào)
/// </summary>
/// <param name="ar">Ar.</param>
void AsyncReceive (System.IAsyncResult ar)
{
//獲取消息套接字
Socket workingClient = ar.AsyncState as Socket;
//完成接收
int msgLength = workingClient.EndReceive (ar);
//如果接收到了數(shù)據(jù)
if (msgLength > 0) {
//消息接收提示
ReceiveCallback ("ReceiveData : " + msgLength + "bytes");
//臨時緩沖區(qū)
byte[] tempBuffer = new byte[msgLength];
//拷貝數(shù)據(jù)到臨時緩沖區(qū)
Buffer.BlockCopy (buffer, 0, tempBuffer, 0, msgLength);
//數(shù)據(jù)放到緩存數(shù)據(jù)組隊尾
cache.AddRange (tempBuffer);
//拆包解析
byte[] result = LengthDecode (ref cache);
//如果已經(jīng)接收完全部數(shù)據(jù)
if (result != null) {
//開始反序列化數(shù)據(jù)
NetModel resultModel = DeSerialize (result);
//TODO:Object Processing!
//數(shù)據(jù)對象結(jié)果提示
ReceiveCallback ("Object Result IP : " + resultModel.senderIp);
ReceiveCallback ("Object Result Content : " + resultModel.content);
ReceiveCallback ("Object Result Time : " + resultModel.time);
}
//消息未接收全,繼續(xù)接收
tcpClient.Client.BeginReceive (buffer, 0, 1024, SocketFlags.None, AsyncReceive, tcpClient.Client);
}
}
#endregion
#region Client Part
/// <summary>
/// 客戶端連接
/// </summary>
public void ClientConnnect ()
{
//連接到服務(wù)器
tcpClient.Connect (serverIPEndPoint);
//連接到服務(wù)器提示
ReceiveCallback ("Has Connect To Server : " + serverIPEndPoint.Address.ToString ());
}
/// <summary>
/// 發(fā)送消息
/// </summary>
/// <param name="model">Model.</param>
public void SendMsg (NetModel model)
{
//將數(shù)據(jù)對象序列化
buffer = Serialize (model);
//將序列化后的數(shù)據(jù)加字節(jié)頭
buffer = LengthEncode (buffer);
//拆分數(shù)據(jù),多次發(fā)送
for (int i = 0; i < buffer.Length/1024 + 1; i++) {
//滿發(fā)送,1KB
int needSendBytes = 1024;
//最后一次發(fā)送,剩余字節(jié)
if (i == buffer.Length / 1024) {
//計算剩余字節(jié)
needSendBytes = buffer.Length - i * 1024;
}
//發(fā)送本次數(shù)據(jù)
tcpClient.GetStream ().Write (buffer, i * 1024, needSendBytes);
}
}
#endregion
//數(shù)據(jù)加字節(jié)頭操作
byte[] LengthEncode (byte[] data)
{
//內(nèi)存流實例
using (MemoryStream ms = new MemoryStream()) {
//二進制流寫操作實例
using (BinaryWriter bw = new BinaryWriter(ms)) {
//先寫入字節(jié)長度
bw.Write (data.Length);
//再寫入所有數(shù)據(jù)
bw.Write (data);
//臨時結(jié)果
byte[] result = new byte[ms.Length];
//將寫好的流數(shù)據(jù)放入臨時結(jié)果
Buffer.BlockCopy (ms.GetBuffer (), 0, result, 0, (int)ms.Length);
//返回臨時結(jié)果
return result;
}
}
}
// 數(shù)據(jù)解析,拆解字節(jié)頭,獲取數(shù)據(jù).
// <returns>源數(shù)據(jù).</returns>
// <param name="cache">緩存數(shù)據(jù).</param>
byte[] LengthDecode (ref List<byte> cache)
{
//如果字節(jié)數(shù)小于4,出現(xiàn)異常
if (cache.Count < 4)
return null;
//內(nèi)存流實例
using (MemoryStream ms = new MemoryStream(cache.ToArray())) {
//二進制流讀操作實例
using (BinaryReader br = new BinaryReader(ms)) {
//先讀取數(shù)據(jù)長度,一個int值
int realMsgLength = br.ReadInt32 ();
//如果未接收全數(shù)據(jù),下次繼續(xù)接收
if (realMsgLength > ms.Length - ms.Position) {
return null;
}
//接收完,讀取所有數(shù)據(jù)
byte[] result = br.ReadBytes (realMsgLength);
//清空緩存
cache.Clear ();
//返回結(jié)果
return result;
}
}
}
// 序列化數(shù)據(jù).
/// <param name="mod">數(shù)據(jù)對象.</param>
private byte[] Serialize (NetModel mod)
{
try {
//內(nèi)存流實例
using (MemoryStream ms = new MemoryStream()) {
//ProtoBuf協(xié)議序列化數(shù)據(jù)對象
ProtoBuf.Serializer.Serialize<NetModel> (ms, mod);
//創(chuàng)建臨時結(jié)果數(shù)組
byte[] result = new byte[ms.Length];
//調(diào)整游標位置為0
ms.Position = 0;
//開始讀取,從0到尾
ms.Read (result, 0, result.Length);
//返回結(jié)果
return result;
}
} catch (Exception ex) {
Debug.Log ("Error:" + ex.ToString ());
return null;
}
}
// 反序列化數(shù)據(jù).
/// <returns>數(shù)據(jù)對象.</returns>
/// <param name="data">源數(shù)據(jù).</param>
private NetModel DeSerialize (byte[] data)
{
try {
//內(nèi)存流實例
using (MemoryStream ms = new MemoryStream(data)) {
//調(diào)整游標位置
ms.Position = 0;
//ProtoBuf協(xié)議反序列化數(shù)據(jù)
NetModel mod = ProtoBuf.Serializer.Deserialize<NetModel> (ms);
//返回數(shù)據(jù)對象
return mod;
}
} catch (Exception ex) {
Debug.Log ("Error: " + ex.ToString ());
return null;
}
}
}