0

I am a beginner when it comes to tcp/ip applications. I'm coding a game and recently I added network multiplayer. I used TcpListener and TcpClient objects from System.Net.Sockets to implement networking. Game works great when I test on localhost or LAN. Later, I tested it over a greater distance: between my pc and my azure VM. Results are shocking. Client received only about 7% of messages sent by server. Server received 84% of messages. I know that TCP/IP doesn't understand what message is because it sends data as a stream. This is what I consider a message:

NetworkStream networkStream = ClientSocket.GetStream();
networkStream.Write(_bytes, 0, _bytes.Length); //_bytes is array of bytes
networkStream.Flush();

My server sends about 20-40 messages per second but 99% of them are 10-15 bytes long. Client sends ~4 messages per second. My machine has access to fast and reliable internet connection. I guess that windows azure data center should have good connection as well. How can I improve network performance of my application ?

EDIT: How client is receiving messages:

NetworkStream serverStream = ClientSocket.GetStream();
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, inStream.Length);

I just realized that it might be interpretation error, meaning that data is received but it's somehow misinterpreted. For instace, I also send inside a message number that represents the total count of sent messages. This number is interpreted fine by this 7% of messages received by cleint. However, messages received by server have some strange numbers in them. For example i received message 31,32,33 and then 570425344 then 35 and then 0. So I guess bytes might be offset. I don't know how and why would that happen.

Maciej Szpakowski
  • 571
  • 1
  • 7
  • 22
  • Chunk the data you are sending into larger, fewer messages. – Robert Harvey Aug 18 '14 at 18:21
  • 4
    You basically can't _not_ receive data sent over TCP. How did you determine the 93% loss? @Robert Nagle (on by default) will do that for you. – CodeCaster Aug 18 '14 at 18:22
  • The problem is your receiving code, not your sending code. Show that code. – Scott Chamberlain Aug 18 '14 at 18:44
  • @CodeCaster Every time I send a message with above code I write it to file. Every time i receive a message, I write it to file. I compared these to files. Let me post me receiving piece of code... – Maciej Szpakowski Aug 18 '14 at 19:28
  • Check the return value of Read(). – CodeCaster Aug 18 '14 at 19:41
  • Is there a reason you're using low level TCP/IP? – John Saunders Aug 18 '14 at 19:42
  • @John Saunders Because it takes less time to write your own code than to find something that will work for you. Believe me I tried. Also, TcpClient and TcpListener are higer level wrappers around Socket object or that's what I've read. Marked as duplicate ? It might be, but it's stated very differently, code is different and conditions are different. – Maciej Szpakowski Aug 18 '14 at 20:19
  • I mean, for instance, why not use WCF, or something else higher-level than sockets? – John Saunders Aug 18 '14 at 20:26
  • Ahh, yes WCF. I considered it but couldn't really make it work. Besides, my TcpListener and TcpClient made a connection faster than I excepcted so I've started developing that and I didn't turn back. – Maciej Szpakowski Aug 18 '14 at 20:39
  • Your problem is explained entirely in the Q&A I linked. You don't check the return value for Read or Write and you don't use a framing protocol, so you don't know where one message ends or the other starts nor what you have actually sent or received. To fix this you need to define a protocol, or rather use an existing solution. – CodeCaster Aug 18 '14 at 21:57
  • Yeah, I didn't know I have to do this. Beginner's trap I guess. I thought that if I do Write and Read and pass byte[] buffer as an argument, then everything is done for me :) – Maciej Szpakowski Aug 18 '14 at 22:53

1 Answers1

0

You might not get all data in one chunk. Use the code

var actualReceivedLength = serverStream.Read(inStream, 0, inStream.Length);

and read actualReceivedLength to know how much you received, call Read again until you have read as much as you expect.

Albin Sunnanbo
  • 46,430
  • 8
  • 69
  • 108
  • In fact, the contrary is true. I receive too much in one chunk. Because of that, I process only one message from what is received and discard everything else. That's the answer. However, it might be true that somehow I receive partial message in one "packet" and the rest in next. The major reason for loosing so much data is that it's received but not processed. – Maciej Szpakowski Aug 18 '14 at 21:26
  • @MaciejSzpakowski - That's because you're assuming the length you read will be the actual length sent, and that is not always the case, which is why you have to check the received size so you can know if you have more to read. – Erik Funkenbusch Aug 19 '14 at 02:12