Unity网络通信与端口通信

Unity的网络通信这块是个坑,还有端口通信。

首先是网络通信,网络通信有Udp协议,Tcp短链接,Tcp长连接等等。搜的话网上一大堆代码。

但是我在使用中遇到了一些问题,发送端没啥好说的,主要是接收端。问题如下:

1.首先是接收端写法,在update里面写和在协程里面写都不行,只有在新开的线程中才可以使用,但是

如果关闭的时候没关闭好线程就会导致程序未响应卡死。

2.udp广播在不同平台上有时候接收不到。

using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class UdpServer : MonoBehaviour
{
           //接收的字符串
    //
    public string strRecvData;//接收到的消息
    public bool IsNewRecv;//是否接收到新的消息,当接收到消息将其改为false
    //以下默认都是私有的成员
    Socket socket;          //目标socket
    EndPoint clientEnd;     //客户端
    IPEndPoint ipEnd;       //侦听端口
    string sendStr;         //发送的字符串
    string recvStr;
    byte[] recvData = new byte[1024]; //接收的数据,必须为字节
    byte[] sendData = new byte[1024]; //发送的数据,必须为字节
    int recvLen; //接收的数据长度
    Thread connectThread; //连接线程

    string strTextData = "Data:";
    //初始化
    void InitSocket()
    {
        //定义侦听端口,侦听任何IP
        ipEnd = new IPEndPoint(IPAddress.Any,8088);
        //定义套接字类型,在主线程中定义
        socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        //服务端需要绑定ip
        socket.Bind(ipEnd);
        //定义客户端
        IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
        clientEnd = (EndPoint)sender;
        print("waiting for UDP dgram");

        //开启一个线程连接,必须的,否则主线程卡死
        connectThread = new Thread(new ThreadStart(SocketReceive));
        connectThread.Start();
       // UdpClient cls = new UdpClient();
       // cls.Close();
    }

    void SocketSend(string sendStr)
    {
        //清空发送缓存
        sendData = new byte[1024];
        //数据类型转换
        sendData = Encoding.ASCII.GetBytes(sendStr);
        //发送给指定客户端
        socket.SendTo(sendData, sendData.Length, SocketFlags.None, clientEnd);
    }

    //服务器接收
    void SocketReceive()
    {
       
        //进入接收循环
        while (true)
        {
            //对data清零
            recvData = new byte[1024];
            //获取客户端,获取客户端数据,用引用给客户端赋值
            recvLen = socket.ReceiveFrom(recvData, ref clientEnd);
            //print("message from: " + clientEnd.ToString()); //打印客户端信息
            //输出接收到的数据
            recvStr = Encoding.ASCII.GetString(recvData, 0, recvLen);
            //strTextData += (recvStr+"||");
            if (recvStr.Length>1)
            {
                IsNewRecv = true;
                strRecvData = recvStr;
            }

            //print(recvStr);
            //将接收到的数据经过处理再发送出去
            //sendStr = "From Server: " + recvStr;

           // SocketSend(sendStr);
        }
    }

    //连接关闭
    void SocketQuit()
    {
        //关闭线程
        if (connectThread != null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
        //最后关闭socket
        if (socket != null)
        {
            socket.Close();
        }
    }

    // Use this for initialization
    void Start()
    {
        InitSocket(); //在这里初始化server
    }


    // Update is called once per frame
    void Update()
    {

    }
   //这里使用OnDestroy进程就会完全关掉。OnDestroy
    void OnDestroy()
    {
        SocketQuit();
    }

    //void OnGUI()
    //{
    //    GUILayout.Label(strTextData);
    //}
}
端口通信:Unity端口通信是个坑,接收端接收会将接收的内容分两次获取,比如说我发一个“”Unity”让程序接收,她会先收到一个“U”,再收到一个“nity”。

不知道后续版本会不会修复这个bug。我百度搜了下有篇文章也全篇在说明这个问题。我这里的解决办法就是将两次接收判断一下。如果接收到是一个字符,就等下个字符串接收到表示一次接收。但这样有个问题就是三个字符以下的命令接收就有错误。所以避免发送三个字符以下的代码就可以用(- -)。以下是代码

using UnityEngine;
using System.Collections;
using System.Threading;
using System.Text;
using System.IO.Ports;
using System;
using System.Collections.Generic;
using UnityEngine.UI;

//这里传输的字节数必须大于3才行,不然会出现错误。

public class ComReceive : MonoBehaviour
{
    public Text txtUI;
    public Text txtPCUI;
    public GameObject go;
    public string strtxt = "5";
    public string portName = "COM2";//端口号
    public int baudRate = 9600;//波特率
    public Parity parity = Parity.None;//奇偶校验位
    public int dataBits = 8;//数据位值
    public StopBits stopBits = StopBits.One;//停止位数
    SerialPort sp = null;
    //
    Thread connectThread;//主线程
    byte[] b = new byte[1024];
    string strInfo;
    void Start()
    {
        sp = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
        sp.Open();
        //开启一个线程连接,必须的,否则主线程卡死
        connectThread = new Thread(new ThreadStart(ReceiveMethod));
        connectThread.Start();
    }
    void Update()
    {
        txtUI.text = strtxt;
        go.transform.position = new Vector3(go.transform.position.x, Convert.ToSingle(strtxt) * 0.1f, go.transform.position.z);
        //img.rectTransform.anchoredPosition3D = new Vector3(Convert, img.rectTransform.anchoredPosition3D.y, img.rectTransform.anchoredPosition3D.z);
    }
    private void ReceiveMethod()
    {
        string recvData = "";
        while (true)
        {
            //打开新的串行端口连接
            //丢弃来自串行驱动程序的接收缓冲区的数据
            sp.DiscardInBuffer();
            //丢弃来自串行驱动程序的传输缓冲去的数据
            sp.DiscardOutBuffer();
            //
            int k = sp.Read(b, 0, b.Length);
            string a = Encoding.ASCII.GetString(b, 0, k);
            if (k == 1)
            {
                recvData = a;
            }
            else
            {
                recvData += a;
                strtxt = recvData;
                //  print(recvData);
            }
        }
    }
    private void ReceiveMethod2()
    {

    }
   //这里也一样使用OnDestroy
    //void OnApplicationQuit()OnDestroy
  void OnDestroy()
    {
        sp.Close();
        SocketQuit();
    }
    //连接关闭
    private void SocketQuit()
    {
        //关闭线程
        if (connectThread != null)
        {
            connectThread.Interrupt();
            connectThread.Abort();
        }
    }
}





猜你喜欢

转载自blog.csdn.net/q493201681/article/details/70432412