unity C#实现简单socket通讯框架

Posted 左右...

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity C#实现简单socket通讯框架相关的知识,希望对你有一定的参考价值。

工程源码地址:https://download.csdn.net/download/u014261855/13099895

话不多少,直接上代码:

1.封装socket内核,客户端服务端公用

/// <summary>
    /// socket内核
    /// </summary>
    public class SFxSocket
    
        private Socket _Socket;

        private string _IP;
        private int _Port;

        private Thread _ReveiveThread;
        private bool _ReveiveContral = false;

        private int _BuffLen = 64;

        #region Instance
        public SFxSocket(string ip, int port)
        
            _IP = ip;
            _Port = port;
            _Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        

        public SFxSocket(Socket s)
        
            _Socket = s;
        

        public void Connect()
        
            IPAddress ip = IPAddress.Parse(_IP);
            EndPoint point = new IPEndPoint(ip, _Port);
            _Socket.BeginConnect(point, OnConnect, null);
        

        public void OpenReceive()
        
            Log("OpenReceive");

            _ReveiveContral = true;
            _ReveiveThread = new Thread(ReceiveThread);
            _ReveiveThread.IsBackground = true;
            _ReveiveThread.Start();
        

        public void Send(byte[] buf)
        
            try
            
                _Socket.BeginSend(buf, 0, buf.Length, SocketFlags.None, OnSend, _Socket);
            
            catch (Exception e)
            
                Log("Send:" + e.Message);
            
        

        public void Close()
        
            _ReveiveContral = false;
            //_ReveiveThread.Abort();
            if (_Socket != null)
            
                _Socket.Shutdown(SocketShutdown.Both);
                _Socket.Close();
                _Socket = null;
            
        
        #endregion

        private void ReceiveThread()
        
            while (_ReveiveContral)
            
                if (_Socket == null) continue;

                try
                
                    byte[] buf = new byte[_BuffLen];

                    int size = _Socket.Receive(buf);

                    OnReceive(buf, size);
                
                catch (Exception e)
                
                    Log("ReveiveThread:" + e.Message);
                    break;
                

                Thread.Sleep(100);
            
        

        private void OnConnect(IAsyncResult r)
        
            Log("OnConnect");

            OpenReceive();
        

        private void OnReceive(byte[] buf, int size)
        
            byte[] value = Polling(buf, size);
            if (!CheckZero(value)) return;

            SFxMessagerCenter<int,byte[]>.Broadcast("OnReceiveBuf", this.GetHashCode(), buf);
        

        private void OnSend(IAsyncResult r)
        
            Log("OnSend");
        

        #region Util
        private bool CheckZero(byte[] buf)
        
            for (int i = 0; i < buf.Length; i++)
            
                if (buf[i] != 0) return true;
            
            return false;
        

        private void Log(string log)
        
            SFxMessagerCenter<string>.Broadcast("SFSocketMsg", log);
        

        private byte[] Polling(byte[] buf, int size)
        

            byte[] r = new byte[size];
            for (int i = 0; i < size; i++)
            
                r[i] = buf[i];
            

            return r;
        
        #endregion

    

其中SFxMessagerCenter是我封装的一个简单的消息处理器,集成三个方法Register、UnRegister、Broadcast,详细见工程。

2.封装协议包

/// <summary>
    /// 数据包基类
    /// </summary>
    public class SFxPakage
    
        byte[] _Buffer;

        public virtual void Init(byte[] buf) 
            _Buffer = buf;
        

        public virtual byte[] ToArray() 
            return _Buffer;
        

        public int ReadInt() 
            int r = BitConverter.ToInt32(SFxUtil.GetByte(_Buffer,4),0);
            _Buffer = SFxUtil.RemoveByte(_Buffer,4);
            return r;
        

        public void WriteInt(int parm) 
            byte [] bytes = BitConverter.GetBytes(parm);
            _Buffer = SFxUtil.AddByte(_Buffer,bytes);
         

    

    public class SFxPakageHead : SFxPakage
    
        public int Version = 4096;
        public int ID = 0;

        public static int _BufferSize = 8;
        public static int _Version = 4096;

        public override void Init(byte[] buf)
        
            base.Init(buf);

            Version = ReadInt();
            ID = ReadInt();
        

        public override byte[] ToArray()
        
            WriteInt(Version);
            WriteInt(ID);

            return base.ToArray();
        
    

SFxPakage目前只实现了ReadInt、WriteInt方法,其他字节解析可以看情况增加。

3.封装服务器

/// <summary>
/// 服务端socket
/// 消息:SFSocketMsg 参数string
/// 消息:OnReceivePag 参数int hash, int id,byte[] buf
/// </summary>
public class SFxServer

    Socket _Socket;

    int _Port;

    List<SFxSocket> _SocketServerList = new List<SFxSocket>();

    bool IsActive = false;

    public SFxServer(int port)
    
        IsActive = true;

        _Port = port;
        _Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

    

    public void Open()
    
        IPAddress add = IPAddress.Parse("127.0.0.1");
        EndPoint point = new IPEndPoint(add, _Port);

        _Socket.Bind(point);
        _Socket.Listen(10);

        AcceptThread();

        Console.WriteLine("启动服务");

        SFxMessagerCenter<int, byte[]>.Register("OnReceiveBuf", OnReceive);
    

    public void Close()
    
        Console.WriteLine("关闭服务");

        IsActive = false;

        for (int i = 0; i < _SocketServerList.Count; i++)
        
            _SocketServerList[i].Close();
        

        _SocketServerList.Clear();

        _Socket.Close();
        _Socket = null;
    

    public void SendToAllClient(int id, SFxPakage pakage)
    
        Console.WriteLine("SendToAllClient id = " + id);

        SFxPakageHead head = new SFxPakageHead();
        head.ID = id;

        byte[] sendbuf = SFxUtil.AddByte(head.ToArray(), pakage.ToArray());

        for (int i = 0; i < _SocketServerList.Count; i++)
        
            _SocketServerList[i].Send(sendbuf);
        
    

    public void SendToAllClient(byte [] pakage)
    
        Console.WriteLine("SendToAllClient len = " + pakage.Length);

        for (int i = 0; i < _SocketServerList.Count; i++)
        
            _SocketServerList[i].Send(pakage);
        
    

    void AcceptThread()
    
        Console.WriteLine("开始接收");
        _Socket.BeginAccept(OnAccept, _Socket);
    

    void OnAccept(IAsyncResult r)
    
        if (!IsActive) return;

        Socket s = (Socket)r.AsyncState;
        Socket ar = s.EndAccept(r);

        SFxSocket socketServer = new SFxSocket(ar);
        _SocketServerList.Add(socketServer);
        socketServer.OpenReceive();

        Console.WriteLine("接收到连接 hash = " + socketServer.GetHashCode());

        AcceptThread();
    

    void OnReceive(int socketHash, byte[] buf)
    
        if (buf.Length < SFxPakageHead._BufferSize) return;
        SFxPakageHead head = new SFxPakageHead();
        head.Init(SFxUtil.GetByte(buf, SFxPakageHead._BufferSize));

        if (head.Version == SFxPakageHead._Version)
        
            SFxMessagerCenter<int, int, byte[]>.Broadcast("OnReceivePag", socketHash, head.ID, SFxUtil.RemoveByte(buf, SFxPakageHead._BufferSize));
        
    

    public int GetConnectCount() 
        return _SocketServerList.Count;
    

服务器对象使用简单,直接new一个对象,调用Open()方法即可,需要通讯的话就监听OnReceive的方法。

4.封装客户端

/// <summary>
    /// 客户端socket
    /// 消息:SFSocketMsg 参数string
    /// 消息:OnReceivePag 参数int id, byte[] buf
    /// </summary>
    public class SFxClient
    
        SFxSocket _Socket;

        public SFxClient(string ip,int port) 

            _Socket = new SFxSocket(ip, port);

            SFxMessagerCenter<int, byte[]>.Register("OnReceiveBuf", OnReceive);
        

        public void Connect() 
            if (_Socket != null) _Socket.Connect();
        

        public void Send(int id, SFxPakage pakage) 
            if (_Socket == null) return;

            SFxPakageHead head = new SFxPakageHead();
            head.ID = id;

            byte[] r = SFxUtil.AddByte(head.ToArray(), pakage.ToArray());

            _Socket.Send(r);
        

        public void Close()
        
            if (_Socket != null)
            
                _Socket.Close();
                _Socket = null;
            
        

        void OnReceive(int socketHash, byte[] buf) 
            if (buf.Length < SFxPakageHead._BufferSize) return;
            SFxPakageHead head = new SFxPakageHead();
            head.Init(SFxUtil.GetByte(buf, SFxPakageHead._BufferSize));

            if (head.Version == SFxPakageHead._Version)
            
                SFxMessagerCenter<int, byte[]>.Broadcast("OnReceivePag", head.ID, SFxUtil.RemoveByte(buf, SFxPakageHead._BufferSize));
            
        
    

直接new对象然后connect即可

5.还封装一个SFxHardware对象,用来直接跟服务器进行byte流通信(这里的服务器是外部的socket服务器,非本项目封装服务器对象)大家自己研究。

 

 

以上是关于unity C#实现简单socket通讯框架的主要内容,如果未能解决你的问题,请参考以下文章

GJM: Unity3D基于Socket通讯例子

Unity3D网络通讯--Socket通讯之Tcp通讯

[经验] Java 使用 netty 框架, 向 Unity 客户端的 C# 实现通信[2]

TCP/IP协议学习 基于C# Socket的Web服务器---动态通讯实现

Android轻量级Socket通讯框架

使用C#实现SSLSocket加密通讯