从另一台机器的 IP 收听消息
Listen to message from an IP from another machine
我正在尝试通过 UDP 向 Unity 发送消息。发送消息的机器 IP 为 192.16.14.1
,端口为 3034
。如何在 Unity 应用程序中输入这两个内容?我找到了侦听 UDP 消息的代码,但我无法在此处设置 IP 地址。此外,Unity 应用程序应始终 运行,即使是否发送来自另一台机器的消息也是如此。
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
public class UDP_Listen : MonoBehaviour
{
UdpClient clientData;
int portData = 3034;
public int receiveBufferSize = 120000;
public bool showDebug = false;
IPEndPoint ipEndPointData;
private object obj = null;
private System.AsyncCallback AC;
byte[] receivedBytes;
void Start()
{
InitializeUDPListener();
}
public void InitializeUDPListener()
{
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
clientData = new UdpClient();
clientData.Client.ReceiveBufferSize = receiveBufferSize;
clientData.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true);
clientData.ExclusiveAddressUse = false;
clientData.EnableBroadcast = true;
clientData.Client.Bind(ipEndPointData);
clientData.DontFragment = true;
if (showDebug) Debug.Log("BufSize: " + clientData.Client.ReceiveBufferSize);
AC = new System.AsyncCallback(ReceivedUDPPacket);
clientData.BeginReceive(AC, obj);
Debug.Log("UDP - Start Receiving..");
}
void ReceivedUDPPacket(System.IAsyncResult result)
{
//stopwatch.Start();
receivedBytes = clientData.EndReceive(result, ref ipEndPointData);
ParsePacket();
clientData.BeginReceive(AC, obj);
//stopwatch.Stop();
//Debug.Log(stopwatch.ElapsedTicks);
//stopwatch.Reset();
} // ReceiveCallBack
void ParsePacket()
{
// work with receivedBytes
Debug.Log("receivedBytes len = " + receivedBytes.Length);
}
void OnDestroy()
{
if (clientData != null)
{
clientData.Close();
}
}
}
我想你搞反了。正如您所说,您共享的这段代码用于在所需端口上侦听 UDP 协议。这段代码需要在您的“服务器”中。通过服务器尝试理解为接收方。
在您的共享方法 InitializeUDPListener() 上;我们有这个:
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
这意味着您正在初始化您的 udp 套接字以侦听给定端口上的任何 ip 地址。也就是说,您的服务器已准备就绪,您需要做的是设置客户端,即发送消息的客户端。
这里有一些例子:
public string serverIp = "127.0.0.1"; // your server ip, this one is sending to local host
public int serverPort = 28500; // your server port
public void ClientSendMessage()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse(serverIp);
byte[] sendbuf = Encoding.ASCII.GetBytes("THIS IS A MESSAGE FROM CLIENT!");
IPEndPoint ep = new IPEndPoint(broadcast, serverPort);
s.SendTo(sendbuf, ep);
}
我鼓励您在使用协议之前阅读 UDP/TCP 协议。 MS 有详细的文档。
这里有一些链接:
所以有两个不同的东西:
目前您使用的是同一个
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
两者兼得! (有趣的事实:作为副作用,通过始终使用相同的字段,您基本上允许 任何 发件人,但从这一刻起绑定到该特定发件人)
实际上你配置的很多东西都有默认值所以这里或多或少是我会做的
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
public class UDP_Listen : MonoBehaviour
{
public ushort localReceiverPort = 3034;
public string senderIP = "192.168.111.1";
public ushort remoteSenderPort = 3034;
public bool showDebug = false;
// Thread-safe Queue to handle enqueued actions in the Unity main thread
private readonly ConcurrentQueue<Action> mainThreadActions = new ConcurrentQueue<Action>();
private Thread udpListenerThread;
private void Start()
{
// do your things completely asynchronous in a background thread
udpListenerThread = new Thread(UDPListenerThread);
udpListenerThread.Start();
}
private void Update()
{
// in the Unity main thread work off the actions
while (mainThreadActions.TryDequeue(out var action))
{
action?.Invoke();
}
}
private void UDPListenerThread()
{
UdpClient udpClient = null;
try
{
// local end point listens on any local IP
var localEndpoint = new IPEndPoint(IPAddress.Any, localReceiverPort);
udpClient = new UdpClient(localEndpoint);
if (showDebug)
{
Debug.Log("BufSize: " + clientData.Client.ReceiveBufferSize);
}
Debug.Log("UDP - Start Receiving..");
// endless loop -> ok since in a thread and containing blocking call(s)
while (true)
{
// remote sender endpoint -> listens only to specific IP
var expectedSenderEndpoint = new IPEndPoint(IPAddress.Parse(senderIP), remoteSenderPort);
// blocking call - but doesn't matter since this is a thread
var receivedBytes = udpClient.Receive(ref expectedSenderEndpoint);
// parse the bytes here
// do any expensive work while still on a background thread
mainThreadActions.Enqueue(() =>
{
// Put anything in here that is required to happen in the Unity main thread
// so basically anything using GameObject, Transform, etc
});
}
}
// thrown for "Abort"
catch (ThreadAbortException)
{
Debug.Log("UDP Listener terminated");
}
// Catch but Log any other exception
catch (Exception e)
{
Debug.LogException(e);
}
// This is run even if an exception happend
finally
{
// either way dispose the UDP client
udpClient?.Dispose();
}
}
private void OnDestroy()
{
udpListenerThread?.Abort();
}
}
我敢肯定,使用 BeginReceive
/EndReceive
或基于任务的替代方案也可以完成同样的工作,但由于它会 运行 无休止,所以我个人找到了一个线程通常更易于阅读和维护。
如果 Unity 应用程序要不断接收消息,它需要类似于:
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("192.16.14.1"), 3034);
while (true)
{
byte[] bytes = listener.Receive(ref groupEP);
}
这应该只读取来自特定 IP 的调用,不确定您希望 UDPClient 从哪个端口读取(在 UDPClient 构造函数中指定),但您可以将其设置为您需要的任何值。
我正在尝试通过 UDP 向 Unity 发送消息。发送消息的机器 IP 为 192.16.14.1
,端口为 3034
。如何在 Unity 应用程序中输入这两个内容?我找到了侦听 UDP 消息的代码,但我无法在此处设置 IP 地址。此外,Unity 应用程序应始终 运行,即使是否发送来自另一台机器的消息也是如此。
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using UnityEngine;
public class UDP_Listen : MonoBehaviour
{
UdpClient clientData;
int portData = 3034;
public int receiveBufferSize = 120000;
public bool showDebug = false;
IPEndPoint ipEndPointData;
private object obj = null;
private System.AsyncCallback AC;
byte[] receivedBytes;
void Start()
{
InitializeUDPListener();
}
public void InitializeUDPListener()
{
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
clientData = new UdpClient();
clientData.Client.ReceiveBufferSize = receiveBufferSize;
clientData.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, optionValue: true);
clientData.ExclusiveAddressUse = false;
clientData.EnableBroadcast = true;
clientData.Client.Bind(ipEndPointData);
clientData.DontFragment = true;
if (showDebug) Debug.Log("BufSize: " + clientData.Client.ReceiveBufferSize);
AC = new System.AsyncCallback(ReceivedUDPPacket);
clientData.BeginReceive(AC, obj);
Debug.Log("UDP - Start Receiving..");
}
void ReceivedUDPPacket(System.IAsyncResult result)
{
//stopwatch.Start();
receivedBytes = clientData.EndReceive(result, ref ipEndPointData);
ParsePacket();
clientData.BeginReceive(AC, obj);
//stopwatch.Stop();
//Debug.Log(stopwatch.ElapsedTicks);
//stopwatch.Reset();
} // ReceiveCallBack
void ParsePacket()
{
// work with receivedBytes
Debug.Log("receivedBytes len = " + receivedBytes.Length);
}
void OnDestroy()
{
if (clientData != null)
{
clientData.Close();
}
}
}
我想你搞反了。正如您所说,您共享的这段代码用于在所需端口上侦听 UDP 协议。这段代码需要在您的“服务器”中。通过服务器尝试理解为接收方。
在您的共享方法 InitializeUDPListener() 上;我们有这个:
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
这意味着您正在初始化您的 udp 套接字以侦听给定端口上的任何 ip 地址。也就是说,您的服务器已准备就绪,您需要做的是设置客户端,即发送消息的客户端。
这里有一些例子:
public string serverIp = "127.0.0.1"; // your server ip, this one is sending to local host
public int serverPort = 28500; // your server port
public void ClientSendMessage()
{
Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
IPAddress broadcast = IPAddress.Parse(serverIp);
byte[] sendbuf = Encoding.ASCII.GetBytes("THIS IS A MESSAGE FROM CLIENT!");
IPEndPoint ep = new IPEndPoint(broadcast, serverPort);
s.SendTo(sendbuf, ep);
}
我鼓励您在使用协议之前阅读 UDP/TCP 协议。 MS 有详细的文档。
这里有一些链接:
所以有两个不同的东西:
目前您使用的是同一个
ipEndPointData = new IPEndPoint(IPAddress.Any, portData);
两者兼得! (有趣的事实:作为副作用,通过始终使用相同的字段,您基本上允许 任何 发件人,但从这一刻起绑定到该特定发件人)
实际上你配置的很多东西都有默认值所以这里或多或少是我会做的
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using UnityEngine;
public class UDP_Listen : MonoBehaviour
{
public ushort localReceiverPort = 3034;
public string senderIP = "192.168.111.1";
public ushort remoteSenderPort = 3034;
public bool showDebug = false;
// Thread-safe Queue to handle enqueued actions in the Unity main thread
private readonly ConcurrentQueue<Action> mainThreadActions = new ConcurrentQueue<Action>();
private Thread udpListenerThread;
private void Start()
{
// do your things completely asynchronous in a background thread
udpListenerThread = new Thread(UDPListenerThread);
udpListenerThread.Start();
}
private void Update()
{
// in the Unity main thread work off the actions
while (mainThreadActions.TryDequeue(out var action))
{
action?.Invoke();
}
}
private void UDPListenerThread()
{
UdpClient udpClient = null;
try
{
// local end point listens on any local IP
var localEndpoint = new IPEndPoint(IPAddress.Any, localReceiverPort);
udpClient = new UdpClient(localEndpoint);
if (showDebug)
{
Debug.Log("BufSize: " + clientData.Client.ReceiveBufferSize);
}
Debug.Log("UDP - Start Receiving..");
// endless loop -> ok since in a thread and containing blocking call(s)
while (true)
{
// remote sender endpoint -> listens only to specific IP
var expectedSenderEndpoint = new IPEndPoint(IPAddress.Parse(senderIP), remoteSenderPort);
// blocking call - but doesn't matter since this is a thread
var receivedBytes = udpClient.Receive(ref expectedSenderEndpoint);
// parse the bytes here
// do any expensive work while still on a background thread
mainThreadActions.Enqueue(() =>
{
// Put anything in here that is required to happen in the Unity main thread
// so basically anything using GameObject, Transform, etc
});
}
}
// thrown for "Abort"
catch (ThreadAbortException)
{
Debug.Log("UDP Listener terminated");
}
// Catch but Log any other exception
catch (Exception e)
{
Debug.LogException(e);
}
// This is run even if an exception happend
finally
{
// either way dispose the UDP client
udpClient?.Dispose();
}
}
private void OnDestroy()
{
udpListenerThread?.Abort();
}
}
我敢肯定,使用 BeginReceive
/EndReceive
或基于任务的替代方案也可以完成同样的工作,但由于它会 运行 无休止,所以我个人找到了一个线程通常更易于阅读和维护。
如果 Unity 应用程序要不断接收消息,它需要类似于:
UdpClient listener = new UdpClient(11000);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Parse("192.16.14.1"), 3034);
while (true)
{
byte[] bytes = listener.Receive(ref groupEP);
}
这应该只读取来自特定 IP 的调用,不确定您希望 UDPClient 从哪个端口读取(在 UDPClient 构造函数中指定),但您可以将其设置为您需要的任何值。