欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity Socket发送字符串(客户端)

程序员文章站 2022-07-13 21:57:14
...

Unity Socket发送字符串(客户端)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Net;
using System.Net.Sockets;
using System;
using System.Text;

public class Client : MonoBehaviour
{
    public int Port;
    public string Ip;
    public Socket clientSocket;
    MessageManager msg = new MessageManager();

    private void Start()
    {
        ConnectServer();
    }


    void ConnectServer()
    {
         clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        try
        {
             clientSocket.Connect(Ip, Port);

            if (clientSocket.Connected == true)
            {

                Debug.Log("成功连接");
            }

            ReceiveMessage();
        }

        catch (Exception e)
        {
             Debug.LogWarning("无法连接到服务器" + e);
        }
    }

    public void ReceiveMessage()
    {
        clientSocket.BeginReceive(msg.Data, msg.StartIndex, msg.RemainSize, SocketFlags.None, ReceiveCallBack, null);
    }

     private void ReceiveCallBack(IAsyncResult ar)
    {
        try
        {
            if (clientSocket == null || clientSocket.Connected == false) return;
            int count = clientSocket.EndReceive(ar);


            msg.ReadMessage(count);
            //ReceiveMessageEvent();

            ReceiveMessage();
        }
        catch (Exception e)
        {
            Debug.Log(e);
        }
    }

    ///<summary>
    ///接收消息
    ///</summary>
    private void ReceiveMessageEvent()
    {
        while (true)
        {
            
            //在接受消息之前判断Socket是否连接
            if (clientSocket.Connected == false) break;
            

            //接受消息头(消息长度4字节)
            int HeadLength = 4;
            //存储消息头的所有字节数
            byte[] recvBytesHead = new byte[HeadLength];
            //如果当前需要接收的字节数大于0,则循环接收
            while (HeadLength > 0)
            {
               
                byte[] recvBytes1 = new byte[4];
                //将本次传输已经接收到的字节数置0
                int iBytesHead = 0;
                //如果当前需要接收的字节数大于缓存区大小,则按缓存区大小进行接收,相反则按剩余需要接收的字节数进行接收
                if (HeadLength >= recvBytes1.Length)
                {
                    iBytesHead = clientSocket.Receive(recvBytes1, recvBytes1.Length, 0);
                }
                else
                {
                    iBytesHead = clientSocket.Receive(recvBytes1, HeadLength, 0);
                }
                //将接收到的字节数保存
                recvBytes1.CopyTo(recvBytesHead, recvBytesHead.Length - HeadLength);
                //减去已经接收到的字节数
                HeadLength -= iBytesHead;
            }
            //接收消息体(消息体的长度存储在消息头的4至8索引位置的字节里)
            byte[] bytes = new byte[4];
            Array.Copy(recvBytesHead, 0, bytes, 0, 4);
            int BodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
            //存储消息体的所有字节数
            byte[] recvBytesBody = new byte[BodyLength];
            
            //如果当前需要接收的字节数大于0,则循环接收
            while (BodyLength > 0)
            {
                
                byte[] recvBytes2 = new byte[BodyLength < 1024 ? BodyLength : 1024];
                //将本次传输已经接收到的字节数置0
                int iBytesBody = 0;
                //如果当前需要接收的字节数大于缓存区大小,则按缓存区大小进行接收,相反则按剩余需要接收的字节数进行接收
                if (BodyLength >= recvBytes2.Length)
                {
                    iBytesBody = clientSocket.Receive(recvBytes2, recvBytes2.Length, 0);
                }
                else
                {
                    iBytesBody = clientSocket.Receive(recvBytes2, BodyLength, 0);
                }
                //将接收到的字节数保存
                recvBytes2.CopyTo(recvBytesBody, recvBytesBody.Length - BodyLength);
                //减去已经接收到的字节数
                BodyLength -= iBytesBody;
            }
            
            //一个消息包接收完毕,解析消息包
            UnpackData(recvBytesHead, recvBytesBody);
        }
    }
    /// <summary>
    /// 解析消息包
    /// </summary>
    /// <param name="Head">消息头</param>
    /// <param name="Body">消息体</param>
    public void UnpackData(byte[] Head, byte[] Body)
    {
        byte[] bytes = new byte[4];
        Array.Copy(Head, 0, bytes, 0, 4);
        Debug.Log("接收到数据的长度:" + IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0)));

        bytes = new byte[Body.Length];
        for (int i = 0; i < Body.Length;)
        {
            byte[] _byte = new byte[4];
            Array.Copy(Body, i, _byte, 0, 4);
            i += 4;
            int num = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(_byte, 0));

            _byte = new byte[num];
            Array.Copy(Body, i, _byte, 0, num);
            i += num;
            Debug.Log("接收到数据包中的数据有:" + Encoding.UTF8.GetString(_byte, 0, _byte.Length));


            GameManager.Instance.IsShow(Encoding.UTF8.GetString(_byte, 0, _byte.Length));
        }
    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Text;
using System.Linq;

public class MessageManager
{
    private byte[] data = new byte[1024];
    private int startIndex = 0;

    public byte[] Data
    {
        get { return data; }
    }

    public int StartIndex
    {
        get { return startIndex; }
    }

    public int RemainSize
    {
        get { return data.Length - startIndex; }
    }

    public void ReadMessage(int newDataAmount)
    {
        startIndex += newDataAmount;

        while (true)
        {
            if (startIndex <= 4) return;

            int count = BitConverter.ToInt32(data, 0);

            if ((startIndex - 4) >= count)
            {
                string s = Encoding.UTF8.GetString(data, 4, count);
                Debug.Log("解析出的数据:" + s);
                Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);

                startIndex -= (count + 4);
            }
            else
            {
                break;
            }

        }

    }

}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
    #region 单例
    static GameManager _instance;
    public static GameManager Instance
    {
        get
        {
            return _instance;
        }
    }

    private void Awake()
    {
        _instance = this;
    }
    #endregion

    public Text magText;
    public bool isShow;
    private string msg;

    void Update()
    {
        if (isShow)
        {
            isShow = false;
            magText.text += "\n" + msg;
        }
    }

    public void IsShow(string sendMsg)
    {
        isShow = true;
        msg = sendMsg;
    }
}