c# - Why am I losing bytes from my Socket InputStream? -


i'm creating socket based system communicating between desktop , mobile devices. i'm using simple protocol reading , writing data streams between devices end bytes:

  1. first 4 bytes represent integer, defines type of command executed
  2. next 4 bytes represent integer, length of rest of bytes in stream
  3. the remaining bytes represent payload data, total number of corresponds result of (2.)

i'm able strip off first 4 bytes , resolve command ok, strip off next 4 bytes , resolve length correctly. problem comes when strip off remaining bytes, of them missing, , they're missing front of remaining data.

for example; if command 1, , length 50, there should 50 bytes left in stream there's 46 , it's bytes 0-3 missing.

the starting data follows:

  • command: 1
  • length: 50
  • payload: c:\users\dave\music\offaiah-trouble_(club_mix).mp3

after converting byte array, get:

"\u0001\0\0\02\0\0\0c:\users\dave\music\offaiah-trouble_(club_mix).mp3"

(question - why first integer \u000 in front of , second not?)

here's snippets of code i'm using parse this:

ibuffer inbuffer = new windows.storage.streams.buffer(4); await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none); int command = bitconverter.toint32(inbuffer.toarray(), 0); 

the inbuffer @ point contains: "\u0001\0\0\0", , bitconverter resolves 1

inbuffer = new windows.storage.streams.buffer(4); await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none); int length = bitconverter.toint32(inbuffer.toarray(), 0); 

the inbuffer contains: "2\0\0\0", , bitconverter resolves "50"

inbuffer = new windows.storage.streams.buffer((uint)length); await _socket.inputstream.readasync(inbuffer, (uint)length, inputstreamoptions.partial); string path = encoding.utf8.getstring(inbuffer.toarray()); 

the inbuffer contains: "sers\dave\music\offaiah-trouble_(club_mix).mp3"

where did missing "c:\u" go front of this?

so, realised kept getting down-voted because question wasn't concise , reproducible. created small project demonstrate part of problem, , ironically enough problem went away.

here's code:

public sealed partial class mainpage : page {     private streamsocketlistener _listener;     private streamsocket _client;     private streamsocket _socket;     private hostname _host;     private int _port = 54321;      public mainpage()     {         initializecomponent();         _listener = new streamsocketlistener();         _listener.connectionreceived += async (sender, args) =>         {             _socket = args.socket;             await receive();         };         _host = networkinformation.gethostnames().firstordefault(x => x.ipinformation != null && x.type == hostnametype.ipv4);     }      protected async override void onnavigatedto(navigationeventargs e)     {         base.onnavigatedto(e);         await _listener.bindendpointasync(_host, $"{_port}");         await task.run(async () =>         {             _client = new streamsocket();             await _client.connectasync(_host, $"{_port}");              int command = 1;             byte[] cmd = bitconverter.getbytes(command);             byte[] path = encoding.utf8.getbytes(@"c:\users\dave\music\offaiah-trouble_(club_mix).mp3");             byte[] length = bitconverter.getbytes(path.length);             byte[] result = cmd.concat(length.concat(path)).toarray();             await _client.outputstream.writeasync(result.asbuffer());         });     }      private async task receive()     {         while (true)         {             ibuffer inbuffer = new windows.storage.streams.buffer(4);             await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none);             int command = bitconverter.toint32(inbuffer.toarray(), 0);             //the inbuffer @ point contains: "\u0001\0\0\0", , bitconverter resolves 1              inbuffer = new windows.storage.streams.buffer(4);             await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none);             int length = bitconverter.toint32(inbuffer.toarray(), 0);             //the inbuffer contains: "2\0\0\0", , bitconverter resolves "50"              inbuffer = new windows.storage.streams.buffer((uint)length);             await _socket.inputstream.readasync(inbuffer, (uint)length, inputstreamoptions.partial);             string path = encoding.utf8.getstring(inbuffer.toarray());         }     } } 

if create new blank universal project , run this, you'll see produces correct output.

eventually worked out had race conditions between stream reader , one. in main project, don't read bytes in 1 go. have separate method reading , parsing "command" before passing control off method redirect control 1 of several worker methods service particular command - stripping off length , rest of payload thereafter.

the problem 'command reader' reading 4 bytes stream, before worker read off it's payload.

obviously answer should pause here , wait worker finish, i'm using async , await throughout surprised me having problem. cause missing await, , dreaded async void, follows..

the offending code:

private async task listen() {     while (true)     {         //expects 4 byte packet representing command         debug.writeline($"listening socket command...");         ibuffer inbuffer = new windows.storage.streams.buffer(4);         await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none);         int command = bitconverter.toint32(inbuffer.toarray(), 0);          debug.writeline($"command received: {command}");         parsecommand(command);     } }  private async void parsecommand(int command) {     //... } 

...and ammended version:

private async task listen() {     while (true)     {         //expects 4 byte packet representing command         debug.writeline($"listening socket command...");         ibuffer inbuffer = new windows.storage.streams.buffer(4);         await _socket.inputstream.readasync(inbuffer, 4, inputstreamoptions.none);         int command = bitconverter.toint32(inbuffer.toarray(), 0);          debug.writeline($"command received: {command}");         await parsecommand(command);     } }  private async task parsecommand(int command) {     //... } 

Comments