我正在尝试通过UdpSocket从多播地址接收数据。 在通过套接字发送数据之前,Socket不接收数据。发送后,我可以收到一些包,然后我必须再次发送,然后我才能收到更多的包。同时从其他主机发送的包丢失。 我认为,这不是像这样的防火墙问题:C# UDP Socket doesn't receive data until after data is sent因为whireshark接收所有包。有人能解释一下这种行为吗?
class Program
{
private static UdpClient _mdnsSocket;
private static IPEndPoint _mdnsGroup;
private static IPEndPoint _localEp;
static void Main(string[] args)
{
var interfaces = NetworkInterface.GetAllNetworkInterfaces()
.Where(i => i.OperationalStatus == OperationalStatus.Up)
.ToArray();
for (int i = 0; i < interfaces.Length; ++i)
{
var interf = interfaces[i];
Console.WriteLine("{0}) Name: {1}", i, interf.Name);
}
Console.WriteLine();
do
{
int i;
Console.Write("Interface: ");
var line = Console.ReadLine();
if (int.TryParse(line, out i) && i < interfaces.Length)
{
var addr = interfaces[i].GetIPProperties()
.UnicastAddresses.FirstOrDefault(a => a.Address.AddressFamily == AddressFamily.InterNetwork);
if (addr != null)
{
_localEp = new IPEndPoint(addr.Address, 5353);
Console.WriteLine("Choosen IP: {0}", _localEp);
}
}
} while (_localEp == null);
_mdnsGroup = new IPEndPoint(IPAddress.Parse("224.0.0.251"), 5353);
_mdnsSocket = new UdpClient();
_mdnsSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
_mdnsSocket.ExclusiveAddressUse = false;
_mdnsSocket.Client.Bind(_localEp);
_mdnsSocket.JoinMulticastGroup(_mdnsGroup.Address, _localEp.Address);
BeginReceive();
Console.WriteLine("1 to switch to multicast mode (default)");
Console.WriteLine("2 to switch to unicast mode");
Console.WriteLine("s for sending a message");
Console.WriteLine("ESC for exit");
ConsoleKey key;
IPEndPoint ip = _mdnsGroup;
IPEndPoint unicastip = null;
var mode = "multicast";
do
{
Console.Write("1/2/s/ESC: ");
key = Console.ReadKey().Key;
Console.WriteLine();
switch (key)
{
case ConsoleKey.D1:
ip = _mdnsGroup;
Console.WriteLine("Switched to multicast mode");
mode = "multicast";
break;
case ConsoleKey.D2:
Console.Write("Enter new IP (leave empty to use {0}):", unicastip);
var input = Console.ReadLine();
if (string.IsNullOrEmpty(input))
{
if (unicastip == null)
{
Console.WriteLine("error: no last ip!");
break;
}
ip = unicastip;
Console.WriteLine("Switched to unicast mode");
mode = "unicast";
}
else
{
unicastip = new IPEndPoint(IPAddress.Parse(input), 5353);
ip = unicastip;
Console.WriteLine("Switched to unicast mode");
mode = "unicast";
}
break;
case ConsoleKey.S:
var msg = string.Format("Hello from PC via {0}", mode);
var bytes = Encoding.ASCII.GetBytes(msg);
Console.WriteLine("Sending to {0}", ip);
_mdnsSocket.Send(bytes, bytes.Length, ip);
break;
}
} while (key != ConsoleKey.Escape);
_mdnsSocket.Close();
}
private static void BeginReceive()
{
Console.WriteLine("BeginReceive");
_mdnsSocket.BeginReceive(ReceiveCallback, _mdnsSocket);
}
private static void ReceiveCallback(IAsyncResult ar)
{
try
{
var ep = new IPEndPoint(IPAddress.Any, _mdnsGroup.Port);
var data = _mdnsSocket.EndReceive(ar, ref ep);
var message = Encoding.ASCII.GetString(data);
Console.WriteLine(message);
}
finally
{
BeginReceive();
}
}
}
答案 0 :(得分:0)
毕竟它似乎是防火墙问题。当我明确允许端口5353上的传入UPD时,它正在工作(为什么允许相应程序的所有传入UPD流量都不起作用)。我现在用所谓的hole punching机制解释问题中描述的行为。我错的时候请纠正我。
答案 1 :(得分:0)
这里有同样的问题,但是防火墙没有解决。我正在使用Windows 10专业版。
我发现了另一个不希望有的效果:广播消息没有被接收,但是纯IP消息却被接收。
我发现的唯一解决方法是添加一个计时器,该计时器每10秒发送一次广播的空字节数组,因此通信保持得很好。 问题在于,总是有无用的消息传输到网络,不是那么沉重,但远非最佳。
关闭套接字并重新启动也解决了该问题,但它的速度较慢,并强制GC运行。
我在Unity(Mono)和Visual Studio应用程序上使用相同的UDP类,但是这种“效果”仅在Unity应用程序下发生。 这只会在IPV4套接字上发生,IPV6套接字似乎永远不会停止监听。
我确定这是新操作系统中的某种“停止使用IPV4广播”功能,因为Windows 7可以正常工作。
希望有帮助。