Unable to get UDP.BeginReceive to work in WPF - c#

I have no trouble using a UDPClient's BeginReceive method from a console application. However, I am not able to get this to run from my WPF app. I'm very confused. I am assuming that it has something to do with where I am calling this code from. I am new to WPF. Is there something I'm misunderstanding about UDPClient's binding in WPF?
Does Inheriting from Application so something that could interfere with UDPClient BeginReceive()
Now this code call stack goes from App.xaml.cs, to ButtonClick(), that creates an instance of MachineItem and calls StartMachine. No weird threading or anything going on (unless WPF does something I'm not aware of during a button click). Again, BeginReceive() is called, but if I put a breakpoint in Receive(IAsyncResult res), nothing ever happens.
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();
}
}
Now after button click, this happens:
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");
}
}
Update:
I tried putting this UDP code where the application first starts to further narrow down the problem. I'm still getting the exact same behavior- the Client is able to call BeginReceive(), but then nothing happens even when UDP packets come in, in other words, the async method Receive() is never called...
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");
}
}

I found the problem after many days of fighting this. The Windows Firewall was not allowing the debug build of the app through. This was hard for me to diagnose because because UDPClient.Send() was allowed, but UDPClient.BeginReceive() was not allowed through the firewall. This is easily fixed on windows 10 by going to Control Panel\All Control Panel Items\Windows Defender Firewall\Allowed apps\ and clicking the name of the app. Release version was allowed through, but debug has a different entry than release. Thank you MM8 for the help with sanity checks.

Related

Can't receive Broadcasts in WinRT

I'm trying to receive a broadcast via DatagramSockets in WinRT/C#, but I just don't receive a packet.
To be more specific, this is my code:
public sealed partial class MainPage : Page
{
public MainPage(){
this.InitializeComponent();
}
private DatagramSocket listener;
async private void Loaded(object sender, RoutedEventArgs e) {
listener = new DatagramSocket();
listener.MessageReceived += MessageReceived;
await listener.BindServiceNameAsync("50011");
}
private void MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) {
txtText.Text = "Win :D:D:D:D:D:D:D"; //Breakpoint here
}
}
The program never reaches the breakpoint.
I've set all the correct rights/permissions in the appxmanifest.
The program which sends the broadcast is the following one:
static void Main(string[] args) {
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
sock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);
IPEndPoint iep = new IPEndPoint(IPAddress.Broadcast, 50011);
string hostname = Dns.GetHostName();
byte[] data = new byte[1];
data[0] = 129;
while (true) {
sock.SendTo(data, iep);
Console.WriteLine("Daten gesendet: {0}", data[0]);
Thread.Sleep(1000);
}
}
I know this program works, because I tested it with another little C# programm on the same PC (but not with WinRT functionality, just normal C#). Also it can't be a Firewall- or Routing Problem, because it, as I just mentioned, already worked with a normal C# program (but I already tried turning the firewall off).
I'm currently trying it on a Wifi-Network using Windows 8.1 and have x64 Processor.
Am I missing something? Is it even possible?
I hope somebody of you can help me
(PS: I know it's pretty similar to this post: Can't Receive UDP Windows RT but there hasen't been progress for more than a year so ...)
I solved it.
You just have to send the broadcasts from a different device.
However it doesn't like broadcasts sent from the same device ....

Winforms server socket application

I'm trying to create a winforms application that listens for traffic on port 10000, and basically works as a middle man for a client application and a remote database. It should have a listen and accept thread which opens a separate client thread when a client connects. This client thread would then handle communication with the client program. The listener application has two listboxes with information on the user that is connecting and the action that is being performed.
For now, I'm trying to use the example program Microsoft gives here and modify it according to my needs, but if anyone has any suggestions on where else I might look I'd love to hear it.
As I try to stumble through this, one thing I haven't been able to figure out yet is how to get this listener going without locking down my computer. Here is my form code (including an exit button and a button that clears my listboxes):
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void btnExit_Click(object sender, EventArgs e) {
this.Close();
}
private void btnClearList_Click(object sender, EventArgs e) {
this.lbActionLog.Items.Clear();
this.lbUserLog.Items.Clear();
count = 0;
this.txtCount.Text = count.ToString();
}
private void Form1_Load(object sender, EventArgs e) {
Server begin = new Server();
begin.createListener();
}
}
and here is my listener code that is called with begin.createListener:
int servPort = 10000;
public void createListener() {
// Create an instance of the TcpListener class.
TcpListener tcpListener = null;
IPAddress ipAddress = Dns.GetHostEntry("localhost").AddressList[0];
string output = "";
try {
// Set the listener on the local IP address and specify the port.
//
tcpListener = new TcpListener(ipAddress, servPort);
tcpListener.Start();
output = "Waiting for a connection...";
}
catch (Exception e) {
output = "Error: " + e.ToString();
MessageBox.Show(output);
}
while (true) {
// Always use a Sleep call in a while(true) loop
// to avoid locking up your CPU.
Thread.Sleep(10);
// Create socket
//Socket socket = tcpListener.AcceptSocket();
TcpClient tcpClient = tcpListener.AcceptTcpClient();
// Read the data stream from the client.
byte[] bytes = new byte[256];
NetworkStream stream = tcpClient.GetStream();
stream.Read(bytes, 0, bytes.Length);
SocketHelper helper = new SocketHelper();
helper.processMsg(tcpClient, stream, bytes);
}
}
Right now, this just stops on tcpListener.AcceptSocket. The form never loads, and obviously the listboxes aren't being populated. How can I get this listener going automatically with the start of the application, and still load the form and update the listboxes? I want this application to start and be ready at any time to accept a connection, without needing to have one already sitting there waiting.
You are using a blocking method so that the Form1_Load never ends because it awaits incoming connections.
A simple workaround could be to start a new thread that handles connections:
private void Form1_Load(object sender, EventArgs e) {
new Thread(
() =>
{
Server begin = new Server();
begin.createListener();
}
).Start();
}

Close threads when invoked by user

I have a simple WinForms app that is to serve as a server for multiple TelNet clients. When each one of these clients connects then a new thread is created. This is all working fine. However, I haven't found a suitable way to close these threads when I need to.
All the examples I have found online use Thread.Abort (which I know is a bad idea) or deal with threads created from the same class, which isn't what I need to do.
This is a simplified version of my classes:
Main UI class:
private void btnStart_Click(object sender, EventArgs e)
{
_listener = new TelNetListener(_deviceConnection);
}
private void btnStop_Click(object sender, EventArgs e)
{
// NEED TO SIGNAL Listener and all Client threads to stop here.
}
Listener class (thread created from Main UI class):
public TelNetListener(DeviceConnection deviceConnection)
{
Thread thread = new Thread(() => TelNetListenerStart(deviceConnection));
thread.Start();
}
private void TelNetListenerStart(DeviceConnection deviceConnection)
{
Socket listener;
listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEndPoint);
listener.Listen(100);
_allDone = new ManualResetEvent(false);
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
}
private void AcceptCallBack()
{
telNetClient = new TelNetClient(clientSocket, string.Format("ACTN{0}",
_clientCounter.ToString("D4")));
}
Client class (thread created from Listener class):
public TelNetClient(Socket socket, string clientName)
{
Thread thread = new Thread(() => TelNetClientStart(socket, clientName));
thread.Start();
}
private void TelNetClientStart(Socket socket, string clientName)
{
DeviceConnection deviceConnection = new DeviceConnection();
this.ClientName = clientName;
this.State = new StateObject();
this.State.WorkSocket = socket;
Send(this.State, "Welcome...");
this.State.WorkSocket.BeginReceive(this.State.Buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallBack), this.State);
}
Bare in mind there is a fair amount of code missing, so if there are undeclared variables or anything like that, just ignore them. I just didn't want to put in loads of irrelevant code.
I have seen examples using a ManualResetEvent which seems to be what I need to do, but I'm not sure where to place it so that all the threads will work off it. Maybe I need 2, one for the Main class to signal the Listener class and from there another to signal all the Client classes?
Could anyone help me with this please as it is pretty much the last part of the infrastructure needed for this project.
If you need any more information I will try and provide it.
Change the code:
while (true)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
with some variable in your class which you can set.
while (this.Work)
{
_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptCallBack), listener);
_allDone.WaitOne();
}
When you want to stop a listener you simply set the Work property to false.

Bind multiple listener to the same port

I am using UdpClient class in .net 3.5
I need to bind multiple applications to the same port .
So, if UDP servers broadcast any request - all the applications thats listen on the port can receive the message but the problem is, when I try bind to an application to the same port, only one application receive the message and the other does not.
Below is some sample code for the two application:
UdpClient udpClient = new UdpClient();
Thread thread;
IPEndPoint endPoint = new IPEndPoint(IPAddress.Loopback, 11000);
public Form1()
{
//CheckForIllegalCrossThreadCalls = false;
InitializeComponent();
udpClient.ExclusiveAddressUse = false;
udpClient.Client.SetSocketOption(
SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
udpClient.Client.Bind(endPoint);
}
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Escape)
{
thread.Abort();
udpClient.Close();
Close();
}
}
private void ReceiveMessage()
{
//while (true)
//{
// IPEndPoint remoteIPEndPoint = new IPEndPoint(IPAddress.Any, 11000);
// byte[] content = udpClient.Receive(ref endPoint);
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
//if (content.Length > 0)
//{
// string message = Encoding.ASCII.GetString(content);
// this.Invoke(myDelegate, new object[] { message });
//}
// }
}
public void Read_Callback(IAsyncResult ar)
{
try
{
byte[] buffer = udpClient.EndReceive(ar, ref endPoint);
// Process buffer
string s = Encoding.ASCII.GetString(buffer);
// richTextBox1.Text = s;
udpClient.BeginReceive(new AsyncCallback(Read_Callback), null);
}
catch (Exception ex)
{ }
}
PS : I am unable to figure out the reason or am I missing something. ?
That's the nature of sockets. Even in cases (such as UDP) where multiple applications can access the same port, the data is handed out first-come, first-serve. UDP is also designed with minimum overhead, so there isn't even an opportunity to "check the queue," like you (hypothetically) could with TCP.
It's designed around having multiple processes share a server load, alternating who receives the request based on who's idle.
You'd need to build something external to get around this, like a retransmission protocol or a database to make sure every inbound message is shared.
If you can deal with the changes, a smarter way to handle this would be UDP Multicast, where multiple programs essentially enroll to receive group messages. In that case, the single-port restriction can (and should) be abandoned.

UDP sometimes can't receive anything

I have a C# application that receives UDP data from a remote host. I find that sometimes my socket receives nothing and I cant seem to find any clues as to why!
Wireshark tells me my data is being sent from the remote device correctly. I cant seem to get why sometimes I can receive fine, and sometimes I can't.
I don't get any exceptions, but OnRecieve never gets called
Here is my code in case it helps:
class cUdpRx
{
private Thread rxThread = null;
private Socket UdpSocket;
private IPEndPoint localEp;
byte[] byData;
//rxbytes event
public delegate void OnRxBytesEventHandler(byte[] rxBuf);
public event OnRxBytesEventHandler OnRxBytesEvent;
/// <summary>
/// Creates the udp socket
/// </summary>
/// <param name="Port"></param>
/// <returns></returns>
public bool CreateSocket(int Port)
{
try
{
byData = new byte[1500]; //create our buffer
UdpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
UdpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
localEp = new IPEndPoint(IPAddress.Any,Port);
UdpSocket.Bind(localEp);
UdpSocket.BeginReceive(byData,0,byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket);
return true; //seemed to work ok
}
catch
{
Dispose();
return false; //something went wrong, abort
}
}
private void OnRecieve(IAsyncResult iar)
{
byte[] rxData;
int nBytesRec = 0;
Socket socket = (Socket)iar.AsyncState;
try //in case something else has already disposed of the socket
{
nBytesRec = socket.EndReceive(iar);
}
catch
{
Debug.WriteLine("cant access udp rx socket");
}
try
{
if (nBytesRec > 0)
{
rxData = new byte[nBytesRec];
Array.Copy(byData, rxData, nBytesRec); //copy exact data into new array
OnRxBytesEvent(rxData);
}
if(!killThreads)
UdpSocket.BeginReceive(byData, 0, byData.Length, SocketFlags.None, new AsyncCallback(OnRecieve), UdpSocket);
}
catch(SocketException se)
{
Debug.WriteLine(se.ToString());
}
}
Any help would be really appreciated as its stopping me from going forward with my project. Thanks
UPDATE
It seems like using IPAdress.any is the problem. If I change:
localEp = new IPEndPoint(IPAddress.Any,Port);
to
localEp = new IPEndPoint(IPAddress.Parse("192.168.0.33"),Port);
where 192.168.0.33 is the IP address of my computer, it receives data every time.
Can anyone explain why?
It is quite useful to use IPAddress.any and receive from both wireless and wired connections.
IPAddress.any is equivalent to 0.0.0.0 and according to MSDN it should receive on all network interfaces.
The usual cause of such problems is not processing packets fast enough. They fill up socket receive buffer and kernel starts dropping them.
Increase socket receive buffer size to accommodate traffic bursts.
Remove everything non-essential from the fast socket reading path.
Consider simple iterative approach bellow instead of working against thread pool:
rxData = new byte[nBytesRec];
while ( !time_to_stop ) {
int len = socket.Receive( rxData );
OnRxBytesEvent( rxData, len );
}
Your code comments mention multicast. Note that you need to add explicit group membership for that, and the fact that you join a multicast group on an interface (either explicitly or as decided via routing table), so if you want to listen for multicast data on two interfaces you need two sockets.
I just got the same problem and resolve it by set timeTolive to big data.
_client = new UdpClient();
_client.Client.Bind(new IPEndPoint(IPAddress.Any, targetURI.Port));
_client.JoinMulticastGroup(IPAddress.Parse(targetURI.Host) , 250);
timeToLive = 250, it works.
timeToLive = 50 , works or not work alternate happened.
timeToLive = none or 0, not work.

Categories

Resources