Bounding the same UDPClient to two threads

G

Gotch@

Hi,

I'm new to C# and .NET. I'm working on a server application and I
can't achieve a particular functionality: the server opens a UDP
socket throug UDP Client. This is done in the main thread, that will
use this socket to send UDP Packs to other hosts. On a parallel thread
I need to receive the anwers, but, of course, if I use the socket in
the other thread it goes mad... I think because of some concurrency
issue... in particular, when doing a receive on the UDPClient instance
it throws the following exception: System.Net.Sockets.SocketException,
with message saying something like "Connection closed by remote
host" (can't be more precise cos VS or somebody else translates the
message in Italian, my language) and that's very confusing for a UDP
socket. Anyway I guess it can't be trusted cos I'm not playing fair
with threading. Anyway it is not possible to use locks: the blocking
receive freezes everything.

So the question is: I need a sender socket with port number A, cos the
receiver has to know the port to answer to. I need a receiver socket
with the same port number A, in order to receive the response packets.
If I try to create two sockets bound to the same port number it will
get mad cos it's forbidden. If I try using the same socket (UDPClient
sorry) between the two threads it will get mad again because of race
conditions. Of course a solution would be to insert in the message
itself the address of another port in order to avoid this mess, but
I'd like to avoid this for the following reason: there may be a
situation in which the host running the software may be beside a
firewall, or a NAT. If I use the same port both to send and receive, I
think the router or firewall will leave it open and translate it after
a first packet coming from that port passes by. So if I use different
ports this won't work. I not very sure about this effect, but I
remeber Kazaa, Skype and other apps use it. Moreover seems strange
that's it's not possible to achieve such a simple thing....

Hope you have some clue.

Bye All.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Gotch@ said:
Hi,

I'm new to C# and .NET. I'm working on a server application and I
can't achieve a particular functionality: the server opens a UDP
socket throug UDP Client. This is done in the main thread, that will
use this socket to send UDP Packs to other hosts. On a parallel thread
I need to receive the anwers, but, of course, if I use the socket in
the other thread it goes mad... I

If you correctly sync. the access from both thread it should be accesible.
(Not that I think is a good idea)
think because of some concurrency
issue... in particular, when doing a receive on the UDPClient instance
it throws the following exception: System.Net.Sockets.SocketException,
with message saying something like "Connection closed by remote
host" (can't be more precise cos VS or somebody else translates the
message in Italian, my language) and that's very confusing for a UDP
socket. Anyway I guess it can't be trusted cos I'm not playing fair
with threading. Anyway it is not possible to use locks: the blocking
receive freezes everything.


I'm not clear what you want do to. If two threads are extracting data at the
same time, then only one will receive a given "package" and this bit of info
will be lost for the other thread.

What is what you are trying to do?
 
P

Peter Duniho

[...]
in particular, when doing a receive on the UDPClient instance
it throws the following exception: System.Net.Sockets.SocketException,
with message saying something like "Connection closed by remote
host" (can't be more precise cos VS or somebody else translates the
message in Italian, my language) and that's very confusing for a UDP
socket. Anyway I guess it can't be trusted cos I'm not playing fair
with threading. Anyway it is not possible to use locks: the blocking
receive freezes everything.

You are completely on the wrong track here. There is absolutely nothing
wrong with using a UDPClient created in one thread from a different
thread, and in fact that's exactly how the async methods on UDPClient work
(BeginReceiveFrom(), BeginSendTo()). If you _did_ fail to synchronize
access between threads, I don't think that the WSAECONNRESET error (which
is what it sounds like you're getting) would be what happens. With a UDP
socket that error occurs (from the MSDN documentation): "On a UDP-datagram
socket this error indicates a previous send operation resulted in an ICMP
Port Unreachable message".
So the question is: I need a sender socket with port number A, cos the
receiver has to know the port to answer to.

Yes, the initial communications must be made to a known port.
I need a receiver socket
with the same port number A, in order to receive the response packets.

No, this is not true. Generally, one end will have a known port, while
the other may not. The end that receives the first datagram (which is the
one with the known port) uses something like ReceiveFrom() which returns
the endpoint information for the sender, which can then be used to reply.
The sender can have any IP address and port.
If I try to create two sockets bound to the same port number it will
get mad cos it's forbidden.

Using the same network adapter, yes. This is not allowed. A socket has
to be bound to a unique IP/port combination (there's an exception to this
rule, but I think bringing that up would only confuse matters here).
If I try using the same socket (UDPClient
sorry) between the two threads it will get mad again because of race
conditions.

What race conditions? If you have a bug in your own code, yes...there may
be problems. But there's nothing fundamentally wrong with having one
thread create a UDPClient and having a different thread use it.
Of course a solution would be to insert in the message
itself the address of another port in order to avoid this mess, but
I'd like to avoid this for the following reason: there may be a
situation in which the host running the software may be beside a
firewall, or a NAT.

There is no need to include the local port in the datagram, since the
receiver can obtain that information directly from the ReceiveFrom()
method. In fact, the local port in the datagram may well be the wrong one
to use (and the IP address as well), for the reasons you mention (NAT,
proxy, etc.).
If I use the same port both to send and receive, I
think the router or firewall will leave it open and translate it after
a first packet coming from that port passes by.

There is no need to have matching ports for this to work. There is no
well-defined specification for how NAT routers and proxies work (a plain
firewall should leave the ports and in fact IP addresses alone, but of
course most people aren't using a plain firewall alone), but any modern,
well-behaved one uses a mapping table to maintain state of clients, and
when it sees a particular IP/port sending a UDP datagram to a given
endpoint, then communications received back from that endpoint will be
automatically forwarded back to that particular IP/port, whether the port
matches the destination endpoint or not.
So if I use different
ports this won't work. I not very sure about this effect, but I
remeber Kazaa, Skype and other apps use it. Moreover seems strange
that's it's not possible to achieve such a simple thing....

Yes, it does seem strange. That should be a clue to you that in fact your
assumptions are wrong, and that it IS possible, and that whatever problems
you're having you are misunderstanding.

Pete
 
G

Gotch@

Thanks Pete, indeed there was a BIG misunderstanding: I was thinking
that the WSAECONNRESET exception was due to bad cuncurrent
manipulation of the UDPClient, cos I tought: "Connection reset on
UDP... mmmm something weird is happening" but I completely forgot
about ICMP Port Unreachable messages... I just tought that if a pack
is sent to a "closed" port or unreachable address, it would just have
been lost...

Anyway I'm still not very sure about a thing... First of all let's say
that I did explain myself incorrectly: it is not that I think I have
to use the same port both to send and receive... it is that I want it,
bacause of those routers/nat/firewall superstitions we discussed
above... and moreover now that's not bothering me anymore, I'm more
interested in understending how to achieve such a simple thing....
Well I don't understand very well how to handle concurrency issues by
the threads that are using the socket... See this:


Thread Receiver:

while(true){

client.Receive(); //blocking

}


Thread B

while(true){

client.Send(); //non blocking

}

Now I like to say how can I cleanly access the socket or if aren't
there just any troubles about it. I wan just meaning that, cos if I
use the Monitor for example, I'll get:

Thread Receiver:

while(true){

Monitor(client).Enter()
client.Receive(); //blocking
Monitor(client).Exit()

}


Thread B

while(true){

Monitor(client).Enter()
client.Send(); //non blocking
Monitor(client).Exit()

}

And this will block the Sender thread indefinitely. So?



[...]
in particular, when doing a receive on the UDPClient instance
it throws the following exception: System.Net.Sockets.SocketException,
with message saying something like "Connection closed by remote
host" (can't be more precise cos VS or somebody else translates the
message in Italian, my language) and that's very confusing for a UDP
socket. Anyway I guess it can't be trusted cos I'm not playing fair
with threading. Anyway it is not possible to use locks: the blocking
receive freezes everything.

You are completely on the wrong track here. There is absolutely nothing
wrong with using a UDPClient created in one thread from a different
thread, and in fact that's exactly how the async methods on UDPClient work
(BeginReceiveFrom(), BeginSendTo()). If you _did_ fail to synchronize
access between threads, I don't think that the WSAECONNRESET error (which
is what it sounds like you're getting) would be what happens. With a UDP
socket that error occurs (from the MSDN documentation): "On a UDP-datagram
socket this error indicates a previous send operation resulted in an ICMP
Port Unreachable message".
So the question is: I need a sender socket with port number A, cos the
receiver has to know the port to answer to.

Yes, the initial communications must be made to a known port.
I need a receiver socket
with the same port number A, in order to receive the response packets.

No, this is not true. Generally, one end will have a known port, while
the other may not. The end that receives the first datagram (which is the
one with the known port) uses something like ReceiveFrom() which returns
the endpoint information for the sender, which can then be used to reply.
The sender can have any IP address and port.
If I try to create two sockets bound to the same port number it will
get mad cos it's forbidden.

Using the same network adapter, yes. This is not allowed. A socket has
to be bound to a unique IP/port combination (there's an exception to this
rule, but I think bringing that up would only confuse matters here).
If I try using the same socket (UDPClient
sorry) between the two threads it will get mad again because of race
conditions.

What race conditions? If you have a bug in your own code, yes...there may
be problems. But there's nothing fundamentally wrong with having one
thread create a UDPClient and having a different thread use it.
Of course a solution would be to insert in the message
itself the address of another port in order to avoid this mess, but
I'd like to avoid this for the following reason: there may be a
situation in which the host running the software may be beside a
firewall, or a NAT.

There is no need to include the local port in the datagram, since the
receiver can obtain that information directly from the ReceiveFrom()
method. In fact, the local port in the datagram may well be the wrong one
to use (and the IP address as well), for the reasons you mention (NAT,
proxy, etc.).
If I use the same port both to send and receive, I
think the router or firewall will leave it open and translate it after
a first packet coming from that port passes by.

There is no need to have matching ports for this to work. There is no
well-defined specification for how NAT routers and proxies work (a plain
firewall should leave the ports and in fact IP addresses alone, but of
course most people aren't using a plain firewall alone), but any modern,
well-behaved one uses a mapping table to maintain state of clients, and
when it sees a particular IP/port sending a UDP datagram to a given
endpoint, then communications received back from that endpoint will be
automatically forwarded back to that particular IP/port, whether the port
matches the destination endpoint or not.
So if I use different
ports this won't work. I not very sure about this effect, but I
remeber Kazaa, Skype and other apps use it. Moreover seems strange
that's it's not possible to achieve such a simple thing....

Yes, it does seem strange. That should be a clue to you that in fact your
assumptions are wrong, and that it IS possible, and that whatever problems
you're having you are misunderstanding.

Pete
 
P

Peter Duniho

[...]
Anyway I'm still not very sure about a thing... First of all let's say
that I did explain myself incorrectly: it is not that I think I have
to use the same port both to send and receive... it is that I want it,
bacause of those routers/nat/firewall superstitions we discussed
above...

As I mentioned, the presence of a NAT router, proxy server, or firewall
should not require a change in the assignments of ports. Even with the
technique of "port tunneling", the only requirement is that _one_ of the
endpoints involved in the communications have a known port, which is the
same requirement in any case, with or without intermediate network
components.
and moreover now that's not bothering me anymore, I'm more
interested in understending how to achieve such a simple thing....
Well I don't understand very well how to handle concurrency issues by
the threads that are using the socket... See this:

[...]
Thread Receiver

while(true){

Monitor(client).Enter()
client.Receive(); //blocking
Monitor(client).Exit()

}


Thread B

while(true){

Monitor(client).Enter()
client.Send(); //non blocking
Monitor(client).Exit()

}

And this will block the Sender thread indefinitely. So?

I believe that you do not need to synchronize access for those particular
methods. This is based on my knowledge of the underlying Winsock
interface used by the .NET Socket class, which allows simultaneous sending
and receiving from different threads on the same socket. I'm not an
expert in .NET Sockets by any means, but assuming it works in a similar
way, you don't need to synchronize sends and receives even for the same
Socket instance.

The statement in the documentation that the methods in the Socket class
are thread-safe suggest that my assumption is correct.

I do have to question your comments indicating that you receive with a
blocking call and send with a non-blocking call. Both the Receive() and
Send() methods are synchronous, unless you set the Socket.Blocking
property to false, in which case they are both non-blocking (technically
still synchronous, but will complete immediately whether data is available
or not, possibly with the WSAEWOULDBLOCK error). You can't, as far as I
know, have Receive() be blocking but Send() be non-blocking, since the
blocking state is of the Socket instance, not the methods called.

Personally, I recommend learning to use the asynchronous methods for the
Socket class, using the BeginXXX and EndXXX pattern. They are relatively
simple, optimize the use of the Socket for i/o, and don't require a
constantly-present thread committed to processing your socket i/o (well,
not one that you create explicitly, anyway :) ). All you have to do is
call Socket.BeginReceive(), and then when there's actually data to be
received, your provided callback will be called. In there, you call
Socket.EndReceive() to actually receive the data, and then call
Socket.BeginReceive() again to prepare for the next receive.

Socket.BeginSend() works in a similar way, except of course that you would
only call it when you actually have something to send.

Hope that helps.

Pete
 
G

Gotch@

[...]
Anyway I'm still not very sure about a thing... First of all let's say
that I did explain myself incorrectly: it is not that I think I have
to use the same port both to send and receive... it is that I want it,
bacause of those routers/nat/firewall superstitions we discussed
above...

As I mentioned, the presence of a NAT router, proxy server, or firewall
should not require a change in the assignments of ports. Even with the
technique of "port tunneling", the only requirement is that _one_ of the
endpoints involved in the communications have a known port, which is the
same requirement in any case, with or without intermediate network
components.


and moreover now that's not bothering me anymore, I'm more
interested in understending how to achieve such a simple thing....
Well I don't understand very well how to handle concurrency issues by
the threads that are using the socket... See this:
[...]
Thread Receiver
while(true){

Monitor(client).Enter()
client.Receive(); //blocking
Monitor(client).Exit()

Thread B
while(true){

Monitor(client).Enter()
client.Send(); //non blocking
Monitor(client).Exit()

And this will block the Sender thread indefinitely. So?

I believe that you do not need to synchronize access for those particular
methods. This is based on my knowledge of the underlying Winsock
interface used by the .NET Socket class, which allows simultaneous sending
and receiving from different threads on the same socket. I'm not an
expert in .NET Sockets by any means, but assuming it works in a similar
way, you don't need to synchronize sends and receives even for the same
Socket instance.

The statement in the documentation that the methods in the Socket class
are thread-safe suggest that my assumption is correct.

I do have to question your comments indicating that you receive with a
blocking call and send with a non-blocking call. Both the Receive() and
Send() methods are synchronous, unless you set the Socket.Blocking
property to false, in which case they are both non-blocking (technically
still synchronous, but will complete immediately whether data is available
or not, possibly with the WSAEWOULDBLOCK error). You can't, as far as I
know, have Receive() be blocking but Send() be non-blocking, since the
blocking state is of the Socket instance, not the methods called.

Personally, I recommend learning to use the asynchronous methods for the
Socket class, using the BeginXXX and EndXXX pattern. They are relatively
simple, optimize the use of the Socket for i/o, and don't require a
constantly-present thread committed to processing your socket i/o (well,
not one that you create explicitly, anyway :) ). All you have to do is
call Socket.BeginReceive(), and then when there's actually data to be
received, your provided callback will be called. In there, you call
Socket.EndReceive() to actually receive the data, and then call
Socket.BeginReceive() again to prepare for the next receive.

Socket.BeginSend() works in a similar way, except of course that you would
only call it when you actually have something to send.

Hope that helps.

Pete

It did, thaks a lot mate. Bye.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top