NetUtility

2018-03-26  本文已影响0人  醉酒青牛_fa4e

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 ();
//消息回调
private NetEventHandler ReceiveCallback;
//服务器Tcp
private TcpListener tcpServer;
//客户端Tcp
private TcpClient tcpClient;
//缓冲区
private byte[] buffer;
//缓存数据组
private List<byte> cache;
//网络节点
private IPEndPoint serverIPEndPoint;

/// <summary>
/// 设置网络节点
/// </summary>
/// <param name="ep">网络节点.</param>
public void SetIpAddressAndPort (IPEndPoint ep)
{
    //只写网络节点
    serverIPEndPoint = ep;
}
//设置委托
/// <param name="handler">消息委托.</param>
public void SetDelegate (NetEventHandler handler)
{
    //只写赋值回调
    ReceiveCallback = handler;
}
/// <summary>
/// Initializes a new instance of the <see cref="NetUtility"/> class.
/// </summary>
private NetUtility ()
{
    //服务器实例
    tcpServer = new TcpListener (IPAddress.Any, 23456);
    //客户端实例
    tcpClient = new TcpClient (AddressFamily.InterNetwork);
    //缓冲区初始化
    buffer = new byte[1024];
    //缓存数据组实例
    cache = new List<byte> ();
    //默认网络节点
    serverIPEndPoint = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 23456);
}

#region Server Part:
/// <summary>
/// 开启服务器
/// </summary>
public void ServerStart ()
{
    //开启服务器
    tcpServer.Start (10);
    //服务器开启提示
    ReceiveCallback ("Server Has Init!");
    //开始异步接受客户端的连接请求
    tcpServer.BeginAcceptTcpClient (AsyncAccept, null);
}
/// <summary>
/// 异步连接回调
/// </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>
/// 异步接收消息回调
/// </summary>
/// <param name="ar">Ar.</param>
void AsyncReceive (System.IAsyncResult ar)
{
    //获取消息套接字
    Socket workingClient = ar.AsyncState as Socket;
    //完成接收
    int msgLength = workingClient.EndReceive (ar);
    //如果接收到了数据
    if (msgLength > 0) {
        //消息接收提示
        ReceiveCallback ("ReceiveData : " + msgLength + "bytes");
        //临时缓冲区
        byte[] tempBuffer = new byte[msgLength];
        //拷贝数据到临时缓冲区
        Buffer.BlockCopy (buffer, 0, tempBuffer, 0, msgLength);
        //数据放到缓存数据组队尾
        cache.AddRange (tempBuffer); 
        //拆包解析
        byte[] result = LengthDecode (ref cache);
        //如果已经接收完全部数据
        if (result != null) {
            //开始反序列化数据
            NetModel resultModel = DeSerialize (result);
            //TODO:Object Processing!
            //数据对象结果提示
            ReceiveCallback ("Object Result IP : " + resultModel.senderIp);
            ReceiveCallback ("Object Result Content : " + resultModel.content);
            ReceiveCallback ("Object Result Time : " + resultModel.time);
        }
        //消息未接收全,继续接收
        tcpClient.Client.BeginReceive (buffer, 0, 1024, SocketFlags.None, AsyncReceive, tcpClient.Client);
    }

}
#endregion

#region Client Part
/// <summary>
/// 客户端连接
/// </summary>
public void ClientConnnect ()
{
    //连接到服务器
    tcpClient.Connect (serverIPEndPoint);
    //连接到服务器提示
    ReceiveCallback ("Has Connect To Server : " + serverIPEndPoint.Address.ToString ());
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="model">Model.</param>
public void SendMsg (NetModel model)
{
    //将数据对象序列化
    buffer = Serialize (model);
    //将序列化后的数据加字节头
    buffer = LengthEncode (buffer);
    //拆分数据,多次发送
    for (int i = 0; i < buffer.Length/1024 + 1; i++) {
        //满发送,1KB
        int needSendBytes = 1024;
        //最后一次发送,剩余字节
        if (i == buffer.Length / 1024) {
            //计算剩余字节
            needSendBytes = buffer.Length - i * 1024;
        }
        //发送本次数据
        tcpClient.GetStream ().Write (buffer, i * 1024, needSendBytes);
    }
}
#endregion


//数据加字节头操作
byte[] LengthEncode (byte[] data)
{
    //内存流实例
    using (MemoryStream ms = new MemoryStream()) {
        //二进制流写操作实例
        using (BinaryWriter bw = new BinaryWriter(ms)) {
            //先写入字节长度
            bw.Write (data.Length);
            //再写入所有数据
            bw.Write (data);
            //临时结果
            byte[] result = new byte[ms.Length];
            //将写好的流数据放入临时结果
            Buffer.BlockCopy (ms.GetBuffer (), 0, result, 0, (int)ms.Length);
            //返回临时结果
            return result;
        }
    }
}
// 数据解析,拆解字节头,获取数据.
// <returns>源数据.</returns>
// <param name="cache">缓存数据.</param>
byte[] LengthDecode (ref List<byte> cache)
{
    //如果字节数小于4,出现异常
    if (cache.Count < 4)
        return null;
    //内存流实例
    using (MemoryStream ms = new MemoryStream(cache.ToArray())) {
        //二进制流读操作实例
        using (BinaryReader br = new BinaryReader(ms)) {
            //先读取数据长度,一个int值
            int realMsgLength = br.ReadInt32 ();
            //如果未接收全数据,下次继续接收
            if (realMsgLength > ms.Length - ms.Position) {
                return null;
            }
            //接收完,读取所有数据
            byte[] result = br.ReadBytes (realMsgLength);
            //清空缓存
            cache.Clear ();
            //返回结果
            return result;
        }
    }
}
// 序列化数据.
/// <param name="mod">数据对象.</param>
private byte[] Serialize (NetModel mod)
{
    try {
        //内存流实例
        using (MemoryStream ms = new MemoryStream()) {
            //ProtoBuf协议序列化数据对象
            ProtoBuf.Serializer.Serialize<NetModel> (ms, mod);
            //创建临时结果数组
            byte[] result = new byte[ms.Length];
            //调整游标位置为0
            ms.Position = 0;
            //开始读取,从0到尾
            ms.Read (result, 0, result.Length);
            //返回结果
            return result;
        }
    } catch (Exception ex) {

        Debug.Log ("Error:" + ex.ToString ());
        return null;
    }
}

// 反序列化数据.
/// <returns>数据对象.</returns>
/// <param name="data">源数据.</param>
private NetModel DeSerialize (byte[] data)
{
    try {
        //内存流实例
        using (MemoryStream ms = new MemoryStream(data)) {
            //调整游标位置
            ms.Position = 0;
            //ProtoBuf协议反序列化数据
            NetModel mod = ProtoBuf.Serializer.Deserialize<NetModel> (ms);
            //返回数据对象
            return mod;

        }
    } catch (Exception ex) {
        Debug.Log ("Error: " + ex.ToString ());
        return null;
    }
}

}

上一篇下一篇

猜你喜欢

热点阅读