sockets - A very simple TCP server/client in C# occasionally drops packets. What can I do to prevent this? -


i've got intra-pc communication server / client set send , receive data 1 program - in case, custom server listening text commands , unity3d.

for part, works, every once in awhile, drop packets, , unity not them without multiple attempts. packets seem sent lost, see "sent message" console log. following code server , client:

server:

class tcpgameserver {     public event eventhandler error;      public action<data> adelegate;      tcplistener tcplistener;     tcpclient tcpclient;     client activeclient;      networkstream networkstream;      streamwriter returnwriter;     streamreader streamreader;      timer systemtimer = new timer();     timer pingtimer = new timer();      int port = 8637;      public tcpgameserver()     {         tcplistener = new tcplistener(ipaddress.loopback, port);         systemtimer.elapsed += streamtimer_tick;         systemtimer.autoreset = true;         systemtimer.interval = 2000;          pingtimer.elapsed += pingtimer_tick;         pingtimer.autoreset = true;         pingtimer.interval = 30000;     }      public void openlistener()     {         tcplistener.start();         tcplistener.beginaccepttcpclient(accepttcpcallback, null);         console.writeline("network open.");     }      public void gamelogout()     {         systemtimer.autoreset = false;         systemtimer.stop();          pingtimer.autoreset = false;         pingtimer.stop();          activeclient = null;          returnwriter.dispose();         streamreader.dispose();          console.writeline("the client has logged out successfully.");     }      private void accepttcpcallback(iasyncresult asyncresult)     {         tcpclient = null;         activeclient = null;         returnwriter = null;         streamreader = null;          try         {             tcpclient = tcplistener.endaccepttcpclient(asyncresult);              tcplistener.beginaccepttcpclient(accepttcpcallback, null);               activeclient = new client(tcpclient);             networkstream = activeclient.networkstream;              returnwriter = new streamwriter(tcpclient.getstream());             streamreader = new streamreader(tcpclient.getstream());              console.writeline("client connected successfully.");              data packet = new data();             packet.cmdcommand = command.login;             packet.strname = "server";             packet.strmessage = "loggedin";             sendmessage(packet);               systemtimer.autoreset = true;             systemtimer.enabled = true;             systemtimer.start();              ping();              pingtimer.autoreset = true;             pingtimer.enabled = true;             pingtimer.start();          } catch (exception ex)         {             onerror(tcplistener, ex);             return;         }       }      private void streamtimer_tick(object source, system.timers.elapsedeventargs e)     {         checkstream();     }      private void pingtimer_tick(object source, system.timers.elapsedeventargs e)     {         ping();     }      private void ping()     {         if (tcpclient.connected)         {             data packet = new data();             packet.cmdcommand = command.ping;             packet.strname = "server";             packet.strmessage = "ping";              sendmessage(packet);         }     }       public void checkstream()     {         try         {             if (tcpclient.available > 0 || streamreader.peek() >= 0)             {                 string packetstring = streamreader.readline();                 data packet = jsonconvert.deserializeobject<data>(packetstring);                  switch (packet.cmdcommand)                 {                     case command.logout:                         gamelogout();                         break;                     case command.message:                         if (adelegate != null)                         {                             adelegate(packet);                         }                         break;                     case command.ping:                         console.writeline("pong!");                         break;                }             }         } catch (ioexception e)         {             console.writeline(e.message);         } catch (nullreferenceexception e)         {             console.writeline(e.message);         }     }      public void sendmessage(data packet)     {         if (activeclient != null)         {             string packetmessage = jsonconvert.serializeobject(packet);             returnwriter.writeline(packetmessage);             returnwriter.flush();         }     }       public void onerror(object sender, exception ex)     {         eventhandler handler = error;         if (handler != null)         {             erroreventargs e = new erroreventargs(ex);             handler(sender, e);         }     }      public void registeractiondelegate(action<data> registerdelegate)     {         adelegate += registerdelegate;     }      public void unregisteractiondelegate(action<data> unregisterdelegate)     {         adelegate -= unregisterdelegate;     } }  

client:

public class tcpnetworkclient {      public action<data> packetdelegate;      public tcpclient tcpclient;     int port = 8637;      streamreader streamreader;     streamwriter streamwriter;      timer streamtimer = new timer();      public bool loggedin = false;        public void start()     {         if (loggedin == false)         {             tcpclient = null;             streamtimer.autoreset = true;             streamtimer.interval = 2000;             streamtimer.elapsed += streamtimer_tick;               try             {                 tcpclient = new tcpclient("127.0.0.1", port);                  streamreader = new streamreader(tcpclient.getstream());                 streamwriter = new streamwriter(tcpclient.getstream());                  streamtimer.enabled = true;                 streamtimer.start();             }             catch (exception ex)             {                 debug.log(ex.message);             }         }      }      private void streamtimer_tick(system.object source,    system.timers.elapsedeventargs e)     {         if (tcpclient.available > 0 || streamreader.peek() >= 0)         {             string packetstring = streamreader.readline();             data packet = jsonconvert.deserializeobject<data>(packetstring);              packetdelegate(packet);         }      }      public void logout()     {         data packet = new data();         packet.cmdcommand = command.logout;         packet.strmessage = "logout";         packet.strname = "game";         sendmessage(packet);          if (streamreader != null && streamwriter != null)         {             streamreader.dispose();             streamwriter.dispose();             tcpclient.close();             tcpclient = null;             streamreader = null;             streamwriter = null;         }          streamtimer.stop();     }      public void sendmessage(data packet)     {         string packetmessage = jsonconvert.serializeobject(packet);          try         {             streamwriter.writeline(packetmessage);             streamwriter.flush();         } catch (exception e)         {          }     }      public void registeractiondelegate(action<data> registerdelegate)     {         packetdelegate += registerdelegate;     }      public void unregisteractiondelegate(action<data> unregisterdelegate)     {         packetdelegate -= unregisterdelegate;     } } 

i'm not sure what's going on, or if there more additional checks need add system. note: it's tcp "when" works, can drop client other programs might write may not rely or use unity.

  1. new tcpclient("127.0.0.1", port) not appropriate client. use tcpclient(). there no need specify ip , port, both of end being wrong.
  2. tcpclient.available bug. seem assume tcp packet based. can't test whether full message incoming or not. tcp offers boundaryless stream of bytes. therefore, available check not tell if whole line available. also, there multiple lines. correct way read have reading loop running , reading lines without checking. line arrives processed way. no need timers etc.
  3. the server has same problems.

issue (2) might have caused appearance of lost packets somehow. need fix in case.


Comments

Popular posts from this blog

java - Static nested class instance -

c# - Bluetooth LE CanUpdate Characteristic property -

JavaScript - Replace variable from string in all occurrences -