c# - Cause of high UDP package loss on localhost? -
in wpf
4.0 application, have udp
listener implemented shown below. on windows 7 pc, i'm running both server , client on localhost
.
each received datagram scanline of larger bitmap, after scanlines have been received bitmap shown on ui
thread. seems work. however, 1-50% scanlines missing. expect on weak network connection, not when run locally.
what may cause udp
package loss following piece of code?
ipendpoint endpoint = new ipendpoint(ipaddress.any, port); udpclient = new udpclient(endpoint); udpclient.client.receivebuffersize = 65535; // i've tried many different sizes... var status = new udpstatus() { u = udpclient, e = endpoint }; udpclient.beginreceive(new asynccallback(udpcallback), status); private void udpcallback(iasyncresult ar) { ipendpoint endpoint = ((udpstatus)(ar.asyncstate)).e; udpclient client = ((udpstatus)(ar.asyncstate)).u; byte[] datagram = client.endreceive(ar, ref endpoint); // begin listening next packet not miss any. client.beginreceive(new asynccallback(udpcallback), ar.asyncstate); lock (bufferlock) { // fast processing of datagram. // merely involves copying datagram (scanline) larger buffer. // // when ready: // here can see scanlines missing in larger buffer. } }
if put system.diagnostics.debug.writeline
in callback, package loss increases dramatically. seems small millisecond delay inside callback causes problems. still, same problem seen in release build.
update
the error becomes more frequent when stress ui bit. udpclient
instance executed on main thread?
to avoid thread block issue, try approach uses newer io completion port receive method:
private void onreceive(object sender, socketasynceventargs e) { top: if (e != null) { int length = e.bytestransferred; if (length > 0) { firebytesreceivedfrom(datagram, length, (ipendpoint)e.remoteendpoint); } e.dispose(); // possibly reuse args? } socket s = socket; if (s != null && remoteendpoint != null) { e = new socketasynceventargs(); try { e.remoteendpoint = remoteendpoint; e.setbuffer(datagram, 0, datagram.length); // don't allocate new buffer every time e.completed += onreceive; // uses fast io completion port stuff made available in .net 3.5; it's supposedly better socket selector or old begin/end methods if (!s.receivefromasync(e)) // returns synchronously if data there goto top; // using goto avoid overflowing stack } catch (objectdisposedexception) { // expected after disconnect e.dispose(); logger.info("udp client receive disconnected."); } catch (exception ex) { logger.error("unexpected udp client receive disconnect.", ex); } } }
Comments
Post a Comment