Tcp socket communication in Unity3d (open source)

Open source address: https://github.com/hiramtan/HiSocket_unity

HiSocket_unity


how to use

The latest unity package can be downloaded from this link:Github Releases


Function

  • Tcp socket
  • Udp socket
  • scalable byte table
  • High performance byte block buffer
  • Message registration and callback
  • binary byte message encapsulation
  • Protobuf message encapsulation
  • AES message encryption

Details

  • Both Tcp and Udp use the main thread asynchronous connection method (to avoid the main thread blocking).
  • Starts sending and receiving threads to handle data transfers (improves performance).
  • The API for users to call to send or receive data is in the main thread (convenient to directly manipulate the components of unity)
  • Listen for connection events to get the current connection status.
  • Listen to the receive event to get the received data.
  • There is a byte array queue, which is convenient for testing and data retransmission.
  • High-performance byte buffers avoid repeated application of memory space and reduce GC.
  • If you use the Tcp protocol, you need to implement the IPackage interface to handle sticky packet unpacking.
  • The Ping interface will report an error on the .net2.0 platform because of the bug at the bottom of the mono (no problem with .net 4.6, or you can also use the interface of unity to get Ping, there is sample code in the project)

detail

  • Tcp Transmission Control Protocol

    • Tcp connection Tcp protocol transmits the byte stream, the user needs to split the byte stream to obtain the correct data packet, when creating a socket of the tcp protocol, a Package object needs to be passed in to encapsulate and unpack.

      private IPackage _packer = new Packer();
      void Test()
      {
       _tcp = new TcpConnection(_packer);
      }
      
      public class Packer : IPackage
      {
          public void Unpack(IByteArray reader, Queue<byte[]> receiveQueue)
          {
             //add your unpack logic here
         }
      
         public void Pack(Queue<byte[]> sendQueue, IByteArray writer)
         {
             // add your pack logic here
         }
      }
      
    • connect

      _tcp.Connect("127.0.0.1", 7777);
      
    • Disconnection When it is no longer running, it needs to actively call the interface to disconnect from the server (for example, when responding to the execution of unity's onapplicationquit)

      void OnApplicationQuit()
      {
          _tcp.DisConnect();
      }
      
    • Connection state changes If you want to get the current connection state, you can subscribe to connection state events.

      void Test()
      {
          _tcp.StateChangeEvent += OnState;
      }
      void OnState(SocketState state)
      {
          Debug.Log("current state is: " + state);
          if (state == SocketState.Connected)
          {
              Debug.Log("connect success");
              //can send or receive message
          }
          else if (state == SocketState.DisConnected)
          {
              Debug.Log("connect failed");
          }
          else if (state == SocketState.Connecting)
          {
              Debug.Log("connecting");
          }
      }
      
    • send messages

      void Test()
      {
          var bytes = BitConverter.GetBytes(100);
          _tcp.Send(bytes);
      }
      
    • 接受消息 You can regist receiveevent and when message come from server, this event will be fire.

          void Test()
          {
              _tcp.ReceiveEvent += OnReceive;
          }
          void OnReceive(byte[] bytes)
          {
              Debug.Log("receive msg: " + BitConverter.ToInt32(bytes, 0));
          }
      
    • Packing and Unpacking When the connection is initially created, we define a packer to split the data packet, when sending a message we insert the message length in the data header / when receiving a message we get the size of the data packet according to the message length in the header.

      private bool _isGetHead = false;
      private int _bodyLength;
      public void Unpack(IByteArray reader, Queue<byte[]> receiveQueue)
      {
          if (!_isGetHead)
          {
              if (reader.Length >= 2)//2 is example, get msg's head length
              {
                  var bodyLengthBytes = reader.Read(2);
                  _bodyLength = BitConverter.ToUInt16(bodyLengthBytes, 0);
              }
              else
              {
                  if (reader.Length >= _bodyLength)//get body
                  {
                      var bytes = reader.Read(_bodyLength);
                      receiveQueue.Enqueue(bytes);
                      _isGetHead = false;
                  }
              }
          }
      }
      public void Pack(Queue<byte[]> sendQueue, IByteArray writer)
      {
          var bytesWaitToPack = sendQueue.Dequeue();
          UInt16 length = (UInt16)bytesWaitToPack.Length;//get head lenth
          var bytesHead = BitConverter.GetBytes(length);
          writer.Write(bytesHead);//write head
          writer.Write(bytesWaitToPack);//write body
      }
      
  • Udp

    • Udp connection If you create an upd connection, you need to specify the send and receive buffer size.

      _udp = new UdpConnection(1024);
      
  • Ping

    public int PingTime;
    private Ping p;
    private float timeOut = 1;
    private float lastTime;
    void Start()
    {
        StartCoroutine(Ping());
    }
    IEnumerator Ping()
    {
        p = new Ping("127.0.0.1");
        lastTime = Time.realtimeSinceStartup;
        while (!p.isDone && Time.realtimeSinceStartup - lastTime < 1)
        {
            yield return null;
        }
        PingTime = p.time;
        p.DestroyPing();
        yield return new WaitForSeconds(1);
        StartCoroutine(Ping());
    }
    
  • message registration

  • Protobuf

  • byte message

  • encryption


Tcp Example

The Tcp protocol provides reliable and orderly stream byte transmission. Users need to divide data by themselves. In this framework, the IPackage interface can be inherited.

    private ITcp _tcp;
    private IPackage _packer = new Packer();
    // Use this for initialization
    void Start()
    {
        _tcp = new TcpConnection(_packer);
        _tcp.StateChangeEvent += OnState;
        _tcp.ReceiveEvent += OnReceive;
        Connect();
    }
    void Update()
    {
        _tcp.Run();
    }

    void Connect()
    {
        _tcp.Connect("127.0.0.1", 7777);
    }
    // Update is called once per frame

    void OnState(SocketState state)
    {
        Debug.Log("current state is: " + state);
        if (state == SocketState.Connected)
        {
            Debug.Log("connect success");
            Send();
        }
        else if (state == SocketState.DisConnected)
        {
            Debug.Log("connect failed");
        }
        else if (state == SocketState.Connecting)
        {
            Debug.Log("connecting");
        }
    }
    void OnApplicationQuit()
    {
        _tcp.DisConnect();
    }
    void Send()
    {
        for (int i = 0; i < 10; i++)
        {
            var bytes = BitConverter.GetBytes(i);
            Debug.Log("send message: " + i);
            _tcp.Send(bytes);
        }
    }
    void OnReceive(byte[] bytes)
    {
        Debug.Log("receive msg: " + BitConverter.ToInt32(bytes, 0));
    }
    public class Packer : IPackage
    {
        public void Unpack(IByteArray reader, Queue<byte[]> receiveQueue)
        {
            //add your unpack logic here
            if (reader.Length >= 1024)//1024 is example, it's msg's length
            {
                var bytesWaitToUnpack = reader.Read(1024);
                receiveQueue.Enqueue(bytesWaitToUnpack);
            }
        }

        public void Pack(Queue<byte[]> sendQueue, IByteArray writer)
        {
            var bytesWaitToPack = sendQueue.Dequeue();
            // add your pack logic here
            //

            writer.Write(bytesWaitToPack);
        }
    }

Udp Example

User Datagram Protocol

The Udp protocol provides unreliable message messages, the user cannot know the current connection status, but the message package is complete.

    private UdpConnection _udp;
    // Use this for initialization
    void Start()
    {
        _udp = new UdpConnection(1024);
        _udp.ReceiveEvent += OnReceive;
        Connect();
        Send();
    }
    void Connect()
    {
        _udp.Connect("127.0.0.1", 7777);
    }
    // Update is called once per frame
    void Update()
    {
        _udp.Run();
    }
    void Send()
    {
        for (int i = 0; i < 10; i++)
        {
            var bytes = BitConverter.GetBytes(i);
            _udp.Send(bytes);
            Debug.Log("send message: " + i);
        }
    }
    private void OnApplicationQuit()
    {
        _udp.DisConnect();
    }
    void OnReceive(byte[] bytes)
    {
        Debug.Log("receive bytes: " + BitConverter.ToInt32(bytes, 0));
    }

Message Registration Example

    void RegistMsg()
    {
        MsgRegister.Regist("10001", OnMsg_Bytes);
        MsgRegister.Regist("10002", OnMsg_Protobuf);
    }

    void OnMsg_Bytes(IByteArray byteArray)
    {
        var msg = new MsgBytes(byteArray);
        int getInt = msg.Read<int>();
    }

    void OnMsg_Protobuf(IByteArray byteArray)
    {
        var msg = new MsgProtobuf(byteArray);
        GameObject testClass = msg.Read<GameObject>();//your class's type
        var testName = testClass.name;
    }

Click the link to join the QQ group [83596104]: https://jq.qq.com/?_wv=1027&k=5l6rZEr

support: [email protected]

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324436879&siteId=291194637