无法使 UDP.BeginReceive 在 WPF 中工作
Unable to get UDP.BeginReceive to work in WPF
我可以在控制台应用程序中使用 UDPClient
的 BeginReceive
方法。但是,我无法从我的 WPF 应用程序将此设置为 运行。我很困惑。我假设它与我调用此代码的位置有关。我是 WPF 的新手。我对 UDPClient
在 WPF 中的绑定有什么误解吗?
是否从应用程序继承,因此可能会干扰 UDPClient BeginReceive()
现在此代码调用堆栈从 App.xaml.cs 变为 ButtonClick()
,创建 MachineItem
的实例并调用 StartMachine
。没有奇怪的线程或任何事情发生(除非 WPF 在单击按钮期间做了我不知道的事情)。同样,BeginReceive()
被调用,但如果我在 Receive(IAsyncResult res)
中放置一个断点,则什么也不会发生。
public partial class App : Application
{
//... all the normal stuff here
private void Button_Click(object sender, RoutedEventArgs e)
{
MachineItem currentMachine = (MachineItem)(sender as Button).DataContext;
currentMachine.StartMachine();
}
}
现在点击按钮后,会发生这种情况:
public class MachineItem : INotifyPropertyChanged
{
IPEndPoint sendersEndPoint;
UdpClient listener;
public void StartMachine()
{
listener = new UdpClient
{
ExclusiveAddressUse = false
};
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPAddress ip = System.Net.IPAddress.Parse(this.LocalNIC_IPAddress);
int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
listener.Client.Bind(endPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Thread.Sleep(20000); // this is just for testing purposes
}
private void Receive(IAsyncResult res)
{
byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Console.WriteLine("Received");
}
}
更新:
我尝试将此 UDP 代码放在应用程序首先开始的位置以进一步缩小问题范围。我仍然得到完全相同的行为——客户端能够调用 BeginReceive(),但是即使 UDP 数据包进来也没有任何反应,换句话说,异步方法 Receive() 永远不会被调用...
public partial class WVGUIApp : Application
{
IPEndPoint sendersEndPoint;
UdpClient listener;
void AppStartup(object sender, StartupEventArgs args)
{
LoadMachineData();
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
listener = new UdpClient
{
ExclusiveAddressUse = false
};
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPAddress ip = System.Net.IPAddress.Parse("10.178.100.111");
int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
listener.Client.Bind(endPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
//Thread.Sleep(20000);
}
private void Receive(IAsyncResult res)
{
byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Console.WriteLine("Received");
}
}
经过多天的斗争,我发现了这个问题。 Windows 防火墙不允许应用程序的调试版本通过。这对我来说很难诊断,因为允许 UDPClient.Send(),但不允许 UDPClient.BeginReceive() 通过防火墙。通过转到控制 Panel\All 控制面板 Items\Windows Defender Firewall\Allowed 应用程序\ 并单击应用程序的名称,可以很容易地在 windows 10 上修复此问题。允许发布版本通过,但调试具有与发布不同的条目。感谢 MM8 帮助进行完整性检查。
我可以在控制台应用程序中使用 UDPClient
的 BeginReceive
方法。但是,我无法从我的 WPF 应用程序将此设置为 运行。我很困惑。我假设它与我调用此代码的位置有关。我是 WPF 的新手。我对 UDPClient
在 WPF 中的绑定有什么误解吗?
是否从应用程序继承,因此可能会干扰 UDPClient BeginReceive()
现在此代码调用堆栈从 App.xaml.cs 变为 ButtonClick()
,创建 MachineItem
的实例并调用 StartMachine
。没有奇怪的线程或任何事情发生(除非 WPF 在单击按钮期间做了我不知道的事情)。同样,BeginReceive()
被调用,但如果我在 Receive(IAsyncResult res)
中放置一个断点,则什么也不会发生。
public partial class App : Application
{
//... all the normal stuff here
private void Button_Click(object sender, RoutedEventArgs e)
{
MachineItem currentMachine = (MachineItem)(sender as Button).DataContext;
currentMachine.StartMachine();
}
}
现在点击按钮后,会发生这种情况:
public class MachineItem : INotifyPropertyChanged
{
IPEndPoint sendersEndPoint;
UdpClient listener;
public void StartMachine()
{
listener = new UdpClient
{
ExclusiveAddressUse = false
};
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPAddress ip = System.Net.IPAddress.Parse(this.LocalNIC_IPAddress);
int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
listener.Client.Bind(endPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Thread.Sleep(20000); // this is just for testing purposes
}
private void Receive(IAsyncResult res)
{
byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Console.WriteLine("Received");
}
}
更新: 我尝试将此 UDP 代码放在应用程序首先开始的位置以进一步缩小问题范围。我仍然得到完全相同的行为——客户端能够调用 BeginReceive(),但是即使 UDP 数据包进来也没有任何反应,换句话说,异步方法 Receive() 永远不会被调用...
public partial class WVGUIApp : Application
{
IPEndPoint sendersEndPoint;
UdpClient listener;
void AppStartup(object sender, StartupEventArgs args)
{
LoadMachineData();
MainWindow mainWindow = new MainWindow();
mainWindow.Show();
listener = new UdpClient
{
ExclusiveAddressUse = false
};
listener.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
IPAddress ip = System.Net.IPAddress.Parse("10.178.100.111");
int ipInt = BitConverter.ToInt32(ip.GetAddressBytes(), 0);
IPEndPoint endPoint = new IPEndPoint(ipInt, 60811); //new IPEndPoint(IPAddress.Any, listenPort); this might allow me not to know the IP of this local device!
listener.Client.Bind(endPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
//Thread.Sleep(20000);
}
private void Receive(IAsyncResult res)
{
byte[] bytes = listener.EndReceive(res, ref sendersEndPoint);
listener.BeginReceive(new AsyncCallback(Receive), null);
Console.WriteLine("Received");
}
}
经过多天的斗争,我发现了这个问题。 Windows 防火墙不允许应用程序的调试版本通过。这对我来说很难诊断,因为允许 UDPClient.Send(),但不允许 UDPClient.BeginReceive() 通过防火墙。通过转到控制 Panel\All 控制面板 Items\Windows Defender Firewall\Allowed 应用程序\ 并单击应用程序的名称,可以很容易地在 windows 10 上修复此问题。允许发布版本通过,但调试具有与发布不同的条目。感谢 MM8 帮助进行完整性检查。