关于Unity错误:“ SocketException:每个套接字地址只有一种用法”

问题描述 投票:0回答:1

我想将以下代码分发给用户以接收UDP:

UDPReceive.cs

using UnityEngine;
using System.Collections;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class UDPReceive : MonoBehaviour
{
    int LOCA_LPORT = 22222;
    static UdpClient udp;
    Thread thread;

    void Start ()
    {
        udp = new UdpClient(LOCA_LPORT);
        udp.Client.ReceiveTimeout = 1000;
        thread = new Thread(new ThreadStart(ThreadMethod));
        thread.Start(); 
    }

    void Update ()
    {
    }

    void OnApplicationQuit()
    {
        thread.Abort();
    }

    private static void ThreadMethod()
    {
        while(true)
        {
            IPEndPoint remoteEP = null;
            byte[] data = udp.Receive(ref remoteEP);
            string text = Encoding.ASCII.GetString(data);
            Debug.Log(text);
        }
    } 
}

https://qiita.com/nenjiru/items/8fa8dfb27f55c0205651

但是,如果用户将此文件附加到多个对象上,则会发生错误。

错误信息如下。

"SocketException: Only one usage of each socket address"

System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end)
System.Net.Sockets.UdpClient.InitSocket (System.Net.EndPoint localEP)
System.Net.Sockets.UdpClient..ctor (Int32 port)
UDPReceive.Start () (at Assets/UDPReceive.cs:16)

如果“我”仅使用此文件,则确保没有将其附加到多个对象也没有问题。

但是,当由“其他用户”使用时,用户可能想知道为什么会发生错误。

因此,当用户遇到此错误时,我想给出一条消息,说“此脚本不得附加到多个对象上。”

我该怎么做?

c# unity3d
1个回答
0
投票

why发生的错误是不言自明的,我认为您已经遇到了问题:您只能在一个端口上侦听一次。第二个脚本将需要使用另一个端口。


如何避免它并给出适当的警告/错误?

有很多选择。

  • 一个可能是使用FindObjectsOfType(例如)检查场景中有多少

    private void Awake()
    {
        var instances = FindObjectsOfType<UDPReceive>();
    
        if(instances.Length > 1)
        {
            Debug.LogError("Found multiple instances of UDPReceive! Only one is allowed!");
        }
    }
    
  • [另一个将是经典的Singleton模式

private static UDPReceive instance;

private void Awake()
{
    if(instance && instance != this)
    {
        Debug.LogError("There is already another instance of UDPReceive in the scene! Only one is allowed!", this);
        Debug.LogError("That's true, I am the active instance for this scene", instance);

        this.enabled = false;
        return;
    }

    instance = this;
}
  • 您还可以捕获异常并显示您自己的自定义消息,例如

  • void Start ()
    {
        try
        {
            udp = new UdpClient(LOCA_LPORT);
            udp.Client.ReceiveTimeout = 1000;
            thread = new Thread(new ThreadStart(ThreadMethod));
            thread.Start();
        }
        catch(SocketException e)
        {
            Debug.LogError("UDP cliente has a SocketException." 
               + "/nThis is probably caused by the target port already being used by something else." 
               + "/nMake sure you have only one instance of UDPReceive in your scene and try again", this);
        } 
    }
    

    作为旁注:实际上将可以通过简单地允许开发人员选择其他端口而在同一场景中多次使用:

    [SerializeField] private int LOCA_LPORT = 22222;
    

    这仍然默认使用22222,但现在有人也可以使用自定义的。 (然后,您当然应该将其重命名以符合c#编码约定)

    © www.soinside.com 2019 - 2024. All rights reserved.