Re: Possible bug in .Net 2.0 udp sockets?
- From: "Al Norman" <al.norman@xxxxxxxxx>
- Date: Tue, 3 Oct 2006 11:25:08 -0400
Pardon me for butting in, but you should be able to increase the size of the
queue of UDP messages. We do this (in C++) with the following:
int receivesize = RECEIVEQUEUESIZE;
if (0 != setsockopt(mysocket,SOL_SOCKET,SO_RCVBUF,
(char *)&receivesize,sizeof(receivesize)))
where RECEIVEQUEUESIZE is a #define of 1024*1024
You won't miss any UDP packets with a buffer that large!
al
"Vadym Stetsyak" <vadym_s@xxxxxxx> wrote in message
news:eT6Ncnv5GHA.1256@xxxxxxxxxxxxxxxxxxxxxxx
Hello, Redge!
R> I called BeginReceiveFrom() several times on purpose, since I do not
R> miss any data that arrives at the socket. Have a look at the
R> following
R> code, which is my callback method:
R> public void OnReceive(IAsyncResult result)
R> {
R> SocketState currSocketState = result.AsyncState as SocketState;
R> try
R> {
R> EndPoint remoteEndPoint = new IPEndPoint(0, 0);
R> int bytesRead =
R> currSocketState.UdpSocket.EndReceiveFrom(result,
R> ref remoteEndPoint);
R> // ... do some stuff
R> }
R> finally
R> {
R> currSocketState.BeginReceive(new
R> AsyncCallback(this.OnReceive));
R> }
R> }
That is correct, implementation. And your app won't miss any data, because
after receiving
data you issue another BeginReceiveFrom call - this is correct.
If you don't do that, indeed, UDP stack can drop packets.
But this "dropping" occurs under certain circumstances.
I'll try to explain why this can happen. When Udp stack receives a packet,
it stores it in the queue. It does so with every pending packet. This
queue has
a limit, connected with the size of occupied memory. When this limit is
reached
all subsequent UDP packets will be dropped by the stack.
When you call ReceiveFrom or BeginReceiveFrom you're taking
that packet out of queue ( data is copied to the buffer supplied by the
caller ).
R> If I call BeginReceiveFrom() only once, my server will have a "blind
R>
R> spot" in the time between entering the callback and starting
R>
R> BeginReceiveFrom() again!
R> The msdn article I referred to in my last
R> mail puts it the following
R> way:
R> [quote]
R> UDP will (...) drop packets
R> upon receipt if, even momentarily,
R> BeginReceiveFrom is not active on
R> the socket.
R> (This) problem is the one most easily solved. In my sample
R> receiver
R> code, there's a short span of time between acceptance of a
R> packet and
R> calling another BeginReceiveFrom. Even if this call were the
R> first
R> one
R> in MessageReceivedCallback, there's a still short period
R> when the app
R> isn't listening. One improvement would be activating
R> several
R> instances
R> of BeginReceiveFrom, each with a separate buffer to
R> hold received
R> packets.
R> [/quote]
See the above.
Doing several BeginReceiveFrom calls can lead to unpredictable behavior
To minimize the time between EndReceiveFrom and subsequent BeginReceivFrom
you can enqueue data for processing. The algorithm can be the following:
- received data
- enqueud them in the queue
- issued another receive data
While another thread is taking data from the queue for further processing.
R> And that's exactly what I did. So,
R> you are right, when I limit the
R> number of simultaneous listeners to 1,
R> my application works. But I
R> will
R> lose a lot of incoming packets,
R> especially if there is a high
R> workload.
Did you test packet loss percentage?
Add a counter to the message and check that counter
every time you receive a message.
R> So there is still the
R> question: Is something wrong in my
R> implementation
R> of calling
R> BeginReceiveFrom() multiple times, or is there an error in
R> the .Net
R> Framework? I suppose it's my error, but what is strange is
R> that
R> it
R> works in .Net 1.1 without any problems ...
IMO it is not stable solution.
While experimenting with
your code, I've added two calls to Console.WriteLine().
One after Send and one after Receive, and problem dissapeared.
So, this means that the fact that the code worked under .NET 1.1
doesn't mean that the code is correct.
R> Greetings,
R> Daniel
R> Vadym
R> Stetsyak wrote:
Hello, Redge!
R> implementation.There is subtle bug in your
R> one endpoint.You have multiple listeners and only one socket and
R> had multiple endpoints thenThere is no
purpose creating mutiple listeners. If you
R> per endpoint.it is necessary
to create one listener
I changed your code and bug vanished.
R> Receiver(int numListeners)public
R> this.numListeners = 1;//= numListeners;{
this.inPort = 10000;
....
}
R> I created a client-server UDP application in .Net 1.1.R> A while ago,
R> application connects via UDP to a server; once acknowledged,A
R> client
R> R> server sends the requested data to the client (a video stream).R> the
R> The application has to work over the internet (where the data mayR>
R> crossR>
R> clientR> NATs, routers and firewalls on its way). That's why the
R> EndPoint-object toR> initiates
R> the data transfer, and the server examines the
R> where to send the data.R> find
R> out where the request originates, and
R> (http://msdn.microsoft.com/msdnmag/issues/06/02/UDP/),R> As recommended by an msdn-article
R>
R> socket to listen on a port, and run the commandR> I use one
R> multiple times, each time with a separateR> "BeginReceiveFrom()"
R> this works just fine: in the callback, I callR> buffer.
R> In .Net 1.1,
R> get the data and the endpoint, and use thisR> "EndReceiveFrom()" to
R> requested data to.R> endpoint to send the
R> time to time!R> However, in .Net 2.0, I get a wrong endpoint from
R> I tested this with a simple application:
R> Several sockets that send data, each sending from (= binded to) aR> -
R> different portR>
R> sended fromR> - The data that is sent contains the port it was
R> constructed asR> - One socket listening for incoming udp-packets,
R> "BeginReceiveFrom()" withR> described above (several calls to
separate
R> buffers).
R> application can run on a single computer or on severalR> The test
R> within the same network. In each case, the applicationR> computers
R> port saved in the EndPoint-object with the portR> compares the
R> the received data.R> specified
R> in
R> theR> - In .Net 1.1, this works just fine: the port of
R> equal, BUT:EndPoint-object
R> and
R> in the received buffer are always
R> beginning --R> - In .Net 2.0, I get lots of wrong ports in the
R> "EndReceiveFrom()" is called THER> normally,
R> the port is always false when
R> subsequent calls seem to work fine.FIRST
R> TIME for a buffer; the
R> application, wrong port-information is not only found in(However,
R> in
R> my REAL
R> beginning, but also later on during runtime).the
R>
R> this error can lead to real problems in myR> It is obvious that
R> data to the wrong clients. It is ofR> application, since I send
R> made a mistake in my implementation -- acourse
R> possible that I just
R> have no effect in .Net 1.1, while .Net 2.0 is moremistake
R> that happens to
R> respect.R> delicate in that
R> theR> However, I did not find anything drastically different from
R> of thismsdn
R> samples. I made a class "SocketState", and one instance
class
R> is
R> used for ever "BeginReceiveFrom()":
R> class SocketStateR>
R> private byte[] buffer;R> {
R> private Socket udpSocket;
R>
R> EndPoint remoteEndPoint;R> private int bufferSize;
R> private
R> bufferSize)R> public SocketState(Socket socket, int
R> this.bufferSize = bufferSize;R> {
R> this.udpSocket = socket;
R>
R> byte[bufferSize];R> this.buffer = new
R> (new IPEndPoint(IPAddress.Any, 0));R> this.remoteEndPoint = (EndPoint)
R>
R> }
R> BeginReceive(AsyncCallback callback)R> public void
R> = new byte[bufferSize];R> {
R> this.buffer
R> R> (new IPEndPoint(IPAddress.Any, 0));R> this.remoteEndPoint = (EndPoint)
R> this.udpSocket.BeginReceiveFrom(this.buffer, 0,R>
R> this.buffer.Length,R>
R> this.remoteEndPoint,R> SocketFlags.None, ref
R> callback, this);
R> }
R> // properties omittedR>
R> }
R> number of SocketStates,R> So I create one listening socket and a
R> socket. Then I call "BeginReceive()" onwhich
R> all
R> get a reference to this
R> instance; in the specified callback, I compare bufferevery
R> SocketState
R> endpoint.and
R>
R> code canR> In case somebody wants to take a closer look, the source
be
R> downloaded here:
R> http://www.incognitek.com/user/stuff/MassiveSocketTest.zipR>
R> file contains projects for Visual Studio 2003 and 2005.R> The zip
R> would be appreciated!R> Any help
R> Greetings,
R> Daniel Sperl, Funworld AG
R> Mail: daniel[DOT]sperl[AT]funworld[DOT]comR>
R> Stetsyak--
Regards, Vadym
d be appreciated!www: http://vadmyst.blogspot.com
R> Greetings,
R> Daniel Sperl, Funworld AG
R> Mail: daniel[DOT]sperl[AT]funworld[DOT]com
--
Regards, Vadym Stetsyak
www: http://vadmyst.blogspot.com
--
Regards, Vadym Stetsyak
www: http://vadmyst.blogspot.com
.
- Follow-Ups:
- Re: Possible bug in .Net 2.0 udp sockets?
- From: Peter Duniho
- Re: Possible bug in .Net 2.0 udp sockets?
- References:
- Possible bug in .Net 2.0 udp sockets?
- From: Redge
- Re: Possible bug in .Net 2.0 udp sockets?
- From: Vadym Stetsyak
- Re: Possible bug in .Net 2.0 udp sockets?
- From: Redge
- Re: Possible bug in .Net 2.0 udp sockets?
- From: Vadym Stetsyak
- Possible bug in .Net 2.0 udp sockets?
- Prev by Date: Re: Call managed code from unmanaged
- Next by Date: Re: System.Timers.Timer Issue
- Previous by thread: Re: Possible bug in .Net 2.0 udp sockets?
- Next by thread: Re: Possible bug in .Net 2.0 udp sockets?
- Index(es):