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服务器,非本项目封装服务器对象)大家自己研究。

扫描二维码关注公众号,回复: 14613065 查看本文章

猜你喜欢

转载自blog.csdn.net/u014261855/article/details/109583060
今日推荐