NetUtility

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;
    }
}

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 人們常說,往往是失去以后才知道自己需要什么,自己所愛之人。每次與你的體育課我都會假裝與你相遇在草坪上,與...
    暢悲哀閱讀 213評論 0 0
  • 今天早操送孩子上學后去上班,默默觀察自己對同事的態(tài)度,和同事對我的態(tài)度。想找到能夠走進同事、客戶心里的那個人,我也...
    TA77范麗萍閱讀 194評論 1 2
  • 每天你遇到那么多人,我們或是在人海里匆匆一瞥,或是微笑點頭。我們不沾親帶故,所以從不奢求,從不苛求,從不要求。別人...
    謹言菇?jīng)?/span>閱讀 161評論 0 0

友情鏈接更多精彩內(nèi)容