美文网首页
NetUtility

NetUtility

作者: 醉酒青牛_fa4e | 来源:发表于2018-03-26 23:58 被阅读0次

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

    }

    相关文章

      网友评论

          本文标题:NetUtility

          本文链接:https://www.haomeiwen.com/subject/wfndcftx.html