Unity UDP局域网广播 组播 Android

Unity Android程序,想实现一个局域网会议程序。

一个程序创建好房间后,需要让其他客户端知道,就需要不断往局域网发消息

开始想使用广播,后来改成组播。这里说一下这两种方式吧

一、广播

广播会往局域网所有客户端发送一次消息。

  _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
            _socket.Bind(new IPEndPoint(GetIpAddress(), port));




 private IPAddress GetIpAddress()
    {
        string hostName = Dns.GetHostName();

        IPAddress[] _ipAddress = Dns.GetHostEntry(hostName).AddressList;
        foreach (IPAddress _IPAddress in _ipAddress)
        {
            if (_IPAddress.AddressFamily.ToString() == "InterNetwork")
            {
                ip = _IPAddress.ToString();
                return _IPAddress;
            }
        }
        Debug.LogError("没找到IP");
        return null;
    }

Socket需要设置广播权限

 Broadcastpoint = new IPEndPoint(IPAddress.Broadcast, port);
 byte[] _data = Encoding.UTF8.GetBytes(data);
  _socket.SendTo(_data, Broadcastpoint);

发送消息,需要不停发送,所以要一个定时循环

 EndPoint point = new IPEndPoint(IPAddress.Any, port);
                byte[] message = new byte[1024];
                int length = _socket.ReceiveFrom(message, ref point);
              
                if (length > 0)
                {
                    byte[] getmessage = new byte[length];
                    Array.Copy(message, getmessage, length);
                    string _message = Encoding.UTF8.GetString(getmessage);
                    Debug.Log(_message);
                }

接收消息

二、组播

组播比广播方便,因为是做会议程序,所以只需要把参议人员接收的组播ip设置一致,并把数据发送里面就可以了。不需要自己管理成员。而且节省宽带,不需要循环发给每个成员

  public UDPServer()
    {
        sendclient = new UdpClient();
    }

    public void Send(string multicastIp , params string[] data)
    {
        try
        {
            iep = new IPEndPoint(IPAddress.Parse(multicastIp), port);
            string _data = AppendData(data);
            Debug.LogError(_data);
            byte[] b = Encoding.UTF8.GetBytes(_data);
            sendclient.Send(b, b.Length, iep);

        }
        catch (Exception e)
        {
            Debug.LogError(e);
        }
    }

因为组播ip是需要改变的,搜索房间需要一个组播ip , 房间通信又需要一个,所以ip不能定死。

 recevieclient = new UdpClient(port);
        iep = new IPEndPoint(IPAddress.Parse(multicastIp), port);
        recevieclient.JoinMulticastGroup(IPAddress.Parse(multicastIp));

        Thread _receiveThread = new Thread(new ThreadStart(Received));
        _receiveThread.IsBackground = true;
        _receiveThread.Start();


 public void Received()
    {
        recevie = true;
        while (recevie)
        {
            try
            {
                byte[] message = recevieclient.Receive(ref iep);
                
                string _message = Encoding.UTF8.GetString(message);
                
                UnityThread.Instance.AddAction(delegate
                {
                    MessageManager.Instance.SplitMessage(_message , localIP);
                });
            }
            catch(Exception e)
            {
                Debug.LogError(e);
            }
        }
    }

接收端只要和发送端保持ip 端口一致就行

三、Android 组播问题

Android如果需要接收组播是需要组播锁的

package com.lightin.lightinarforunity;

import android.content.Context;
import android.net.wifi.WifiManager;

public class M_MulticastLock {
    private WifiManager.MulticastLock multicastLock;

    private Context context;

    private   static   M_MulticastLock instance;

    public    static   M_MulticastLock Instance(){
        if(instance == null)
            instance = new  M_MulticastLock();
        return instance;
    }

    public  void Init(Context context)
    {
         this.context = context;
         WifiManager wifiManager=(WifiManager)context.getSystemService(Context.WIFI_SERVICE);
         multicastLock=wifiManager.createMulticastLock("multicast.test");
    }


    public void allowMulticast(){
        multicastLock.acquire();
    }

    public  void closeMulticast(){
        multicastLock.release();
    }
}

单例调用这个类,我是每帧都会调用allowMulticast。只能在主线程调用,不然会报错。

 
 

权限

你可能感兴趣的:(Unity效果实现思路)