1

UDP client only receives a message and freezes

the timer runs only once and do not know how to follow him to clinte UDP messages coming

namespace temp {
    public partial class Form1 : Form
    {  

    }
    public Form1()
    {
        InitializeComponent();    
    }
    private void Form1_Load(object sender, EventArgs e)
    { 

    }
    private void label1_Click(object sender, EventArgs e)
    {

    }
}

only run once

private void timer1_Tick(object sender, EventArgs e) {
    UdpClient client = new UdpClient();
    IPEndPoint localEp = new IPEndPoint(IPAddress.Any, 22);
    client.Client.SetSocketOption(SocketOptionLevel.Socket,           SocketOptionName.ReuseAddress, true);
    client.Client.Bind(localEp);
    IPAddress multicastaddress = IPAddress.Parse("127.0.0.1");
    Byte[] data = client.Receive(ref localEp);
    string mensaje = Encoding.UTF8.GetString(data);
    label1.Text += "" + mensaje.ToString() + "";
}
Micaela
  • 132
  • 13
  • 2
    Isn't this code opening a new client each clock tick and not closing any? – WDS Sep 14 '15 at 08:30
  • 2
    Does it actually receive a message or is it stuck on the synchronous receive message? – James Sep 14 '15 at 08:36
  • 1
    @WDS he says the timer runs only once, if that wasn't true he would get an exception that would block him anyway, when trying to Bind two sockets over the same port. – Stavm Sep 14 '15 at 09:07
  • Why would you use a timer to synchronously receive data from a socket? And why are you listening on a port reserved for SSH, while expecting UTF-8 text? Also, `ReuseAddress` doesn't do what you think it does - it just means that you don't get an error when binding to the same address twice; it doesn't mean that all the listeners get the messages. It's obviously something you tried because you don't dispose of your clients cleanly. Please, don't just guess your way around with networking - it's an immensely complicated subject, and it's very easy to get wrong. Learn what you're doing first. – Luaan Sep 14 '15 at 09:07

1 Answers1

1

The windows forms timer "ticks" on the UI thread. This means that during the time you spend in the timer_tick handler, the UI will not refresh, and your application will appear to be frozen.

The client.Receive() method by default is a blocking operation, meaning that it waits until a message is available.

You'd want to change a few things here:

  • Move the creation of the UdpClient outside the timer_tick function; you only need one instance throughout the application
  • Remove SocketOption.ReuseAddress because you will no longer need it
  • Use asynchronous methods rather than the blocking client.Receive(), so you won't even need the timer anymore.
  • If you don't feel up to the task of asynchronous programming, you could set client.Client.Blocking = false and catch the corresponding SocketException. However, using exceptions for regular control flow is bad.
C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
  • 1
    He should not be using any timers here at all. Also The APM pattern is obsolete. Use await. – usr Sep 14 '15 at 09:27
  • @usr agreed, updated the answer a bit. I don't get to work with the newer frameworks yet, so I kept that direction a bit vague. There should be plenty of examples out there, such as http://stackoverflow.com/a/24154685/292411 – C.Evenhuis Sep 14 '15 at 09:43