3

I'm new to C# UDP coding and I have some 'strange' behaviour when using an UDP client locally on my pc. I want to send UDP data from one port (11000) on my pc to another port (12000) on the same pc.

This is a snippet from my code :

public class MyClass
{
    //Creates a UdpClient for reading incoming data.
    private UdpClient udpClient;
    private Thread thread;
    private const String IPADDR = "127.0.0.1";

    public MyClass()
    {
        udpClient = new UdpClient(11000);
        udpClient.Connect(IPAddress.Parse(IPADDR), 12000);


        this.thread = new Thread(new ThreadStart(this.Execute));
        this.thread.Name = "Udp";
        this.thread.Start();

        SendData("The quick brown fox jumps over the lazy dog");

    }

    private void Execute()
    {
        try
        {

            // Blocks until a message returns on this socket from a remote host.
            IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Any, 0);
            Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);

            Console.WriteLine("Data received");

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


    public void SendData(String data)
    {
        Console.WriteLine("Sending...");
        try
        {
            this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
        }
        catch (Exception e)
        {
            Console.WriteLine(String.Format("Exception {0}", e.Message));
        }
    }
}

If I run this, I get an exception :

Sending...
System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host 
at System.Net.Sockets.Socket.ReceiveFrom(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags, EndPoint& remoteEP)
at System.Net.Sockets.UdpClient.Receive(IPEndPoint& remoteEP)
at test.MyClass.Execute() in C:\Temp\test\Class1.cs:line 40

The exception seems to occur on this line :

Byte[] receiveBytes = this.udpClient.Receive(ref remoteIpEndPoint);

At the moment of the SendData(), the Receive is throwing the exception. When not doing the send, I don't get the exception. It looks like the send is causing the receive to return with an exception.

When I use the real ip address of my pc, I have the same behaviour. However, when I use any other ip address, even if it's unassigned to any pc (e.g. 192.168.10.10), it's working well : it sends the string and the Receive() keeps waiting for incoming data.

svick
  • 236,525
  • 50
  • 385
  • 514
Filip
  • 31
  • 1
  • 2
  • Can you add the code calling `MyClass`? – Jack Hughes Mar 17 '15 at 12:22
  • Code is called through constructor which is what I meant when I said he needs to design it better. – Velja Radenkovic Mar 17 '15 at 12:26
  • By the way: as the person asking the question, one of your responsibilities is to provide feedback for answers given. If you feel that any answer is useful (or specifically not useful), you should use the voting buttons to indicate that. If you feel that any single answer has actually addressed your question in the best way, you should accept that answer by clicking the checkmark button next to the answer. – Peter Duniho Mar 26 '15 at 00:46

2 Answers2

1

The error happens because there is no socket open on the port to which you are sending.

For the purposes of simply testing UDP communications, you can fix your code example simply by changing the port to which you are sending. I.e. change the Connect() method call to this:

udpClient.Connect(IPAddress.Parse(IPADDR), 11000);

This will cause the socket to send to itself. Your code will work successfully with just this change.


For the record, here is about the simplest possible demonstration code that uses UdpClient:

UdpClient client = new UdpClient(0, AddressFamily.InterNetwork);

byte[] datagram = Encoding.ASCII.GetBytes("hello world!");

IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Loopback, ((IPEndPoint)client.Client.LocalEndPoint).Port);

client.Send(datagram, datagram.Length, ipEndPoint);
datagram = client.Receive(ref ipEndPoint);

Console.WriteLine("Received: \"" + Encoding.ASCII.GetString(datagram) + "\"");

Of course, in a real network I/O situation, you will have two endpoints, each bound to its own local port, sending to the other endpoint's port. So neither your code example, nor this simpler one I present is very useful as an actual working program. But it does allow you to learn some things about how the socket API works.

Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
  • How this sends from port 11000 to 12000 ? "I want to send UDP data from one port (11000) on my pc to another port (12000) on the same pc." Isn't that begining of question? This answer: 1. Doesn't answer the question. 2. Has no practical value. – Velja Radenkovic Mar 17 '15 at 12:53
  • What I wanted to do, just for testing, is sending data from my program to another 3rd party program, both on the same machine. So, not sending to my own program. – Filip Mar 17 '15 at 13:13
  • @Filip: well, to do that, you need two programs. You only posted one program. Please edit your question to make it unambiguous; at the moment, it's not clear what you are actually asking. – Peter Duniho Mar 17 '15 at 13:19
  • The problem seems indeed the destination port that was not 'open'. I.e. I made a mistake in the input port configuration of that other program. When its input UDP is configured to 127.0.0.1/12000, my own program isn't throwing the exception anymore. Thanks for the hint...! However, there's still something weird to me : why do I not get the exception for a randomly choosen destination IP address that is not assigned to any pc on our network ? In fact, one should have the same situation, no ? (destination port not open, so one would also expect an exception...) – Filip Mar 17 '15 at 13:21
  • That's an excellent question. Basically, the underlying network transport has complete knowledge of the available ports on your computer, and so if you try to send or receive to/from a non-existent port, the transport can generate an error. But UDP by design simply ignores delivery failures in general, and so when you try to send to a non-existent port at some remote address, the lack of an acknowledgement is "normal". Hence no error in that case. – Peter Duniho Mar 17 '15 at 13:24
  • Thanks Peter for the explanation. In fact, it's a little bit unexpected behaviour for me : UDP is connectionless, so one would expect UDP not bothering about presence of the remote host/port, whether that's on a local machine or on a remote host. Obviously, it behaves different for connections on a local machine. Good to know... – Filip Mar 18 '15 at 07:30
0

You are trying to send from one socket (UdpClient which is socket wrapper) to itself. Thats not how the things work in UDP (nor in other IP protocols). You need 2 sockets. One for sending one for receiving. Connect method is poorly named since UDP protocol is conectionless but thats not your fault.

Other than that you need to put socket in listening state before sending to it. So you first need to start thread that listens and then send.

You need to better design your program but this will work:

class Program
{
    static void Main(string[] args)
    {
        MyClass mc = new MyClass();
    }
}

public class MyClass
{
    //Creates a UdpClient for reading incoming data.
    private UdpClient udpClient;
    private UdpClient recipient;
    private Thread thread;
    private const String IPADDR = "127.0.0.1";

    public MyClass()
    {
        recipient = new UdpClient(new IPEndPoint(IPAddress.Parse(IPADDR), 12000));
        this.thread = new Thread(new ThreadStart(this.Execute));
        this.thread.Name = "Udp";
        this.thread.Start();

        udpClient = new UdpClient(11000);
        udpClient.Connect(IPAddress.Parse(IPADDR), 12000);

        SendData("The quick brown fox jumps over the lazy dog");
    }

    private void Execute()
    {
        try
        {
            // Blocks until a message returns on this socket from a remote host.
            IPEndPoint remoteIpEndPoint = new IPEndPoint(IPAddress.Parse(IPADDR), 11000);

            Byte[] receiveBytes = this.recipient.Receive(ref remoteIpEndPoint);

            Console.WriteLine("Data received: " + Encoding.ASCII.GetString(receiveBytes));

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
    }


    public void SendData(String data)
    {
        Console.WriteLine("Sending...");
        try
        {
            this.udpClient.Send(System.Text.Encoding.ASCII.GetBytes(data), data.Length);
        }
        catch (Exception e)
        {
            Console.WriteLine(String.Format("Exception {0}", e.Message));
        }
   }
}
Velja Radenkovic
  • 716
  • 1
  • 6
  • 27
  • Actually, UDP sockets are always in a "listening" state, datagrams are buffered (so you don't _necessarily_ need to have already called `ReceiveFrom()` or similar before a datagram is sent), and a UDP socket most certainly can receive a datagram from itself. Now, whether sending to oneself makes sense is a different question; it's useful for testing code, but obviously has limited value in a real-world application. But it doesn't explain the exception that the OP is getting, which limits the usefulness of this answer significantly (since it fails to address the actual question). – Peter Duniho Mar 17 '15 at 12:36
  • So 1 UDP socket can send to itself from udp port 11000 to 12000 ? Please continue. I would love to hear about 2 port sockets. – Velja Radenkovic Mar 17 '15 at 12:42
  • I never said that. I said a UDP socket can send to _itself_. If it's bound to port 11000, then it has to send to port 11000 to receive what it sent to itself. – Peter Duniho Mar 17 '15 at 12:45
  • @VeljaRadenkovic: So what you really wanted to say was that one socket cannot be bound to two ports? Adjust your answer then. – jgauffin Mar 17 '15 at 12:52
  • I am sorry I don't understand whats unclear? Please edit if you think its unclear I don't mind it. You obviously can't have 1 socket selfsending / selfreceiving to from one port to another port its already kills definition of socket. Or suggest me an edit and I will do it. – Velja Radenkovic Mar 17 '15 at 12:59