2

i have a problem :

My model is 1 Server serving lots Clients at the same time using TCP socket model. Codes usually work fine and never throw any exception, but sometime a connection between Server and a Client gose like this :

+)Client sends successfully data to Server (i know this because of using WireShark to catch every packets on Server's side)

+)Server socket.Receive(buffer) displays none of the datas above. (why tho?) //its a loop for receiving, so it has to be some datas after a zero-receive right? but looks like it stops receiving like forever.

+)Server sends data to Client (it sends usually, often per 500ms)

+)Client still able to receive datas from Server

And the circle continues like that.

i need to know why Server keeps "refusing"(idk) datas from Client like that while the connection looks fine?

Here is method Send i use for both sides : Socket.Send(Encoding.UTF8.GetBytes("Message$");

Here is the method Receive that i use for both sides, note that every messages end with "$" to separate them on other side.

int Signal(Socket s, byte[] b)
    {
        int k = 0;
        try { k = s.Receive(b); return k; } catch { return 0; }
    }

void Receiverr(Socket s){
     new thread(()=>
     {byte[] byteReceive = new byte[1024];
            Array.Clear(byteReceive, 0, byteReceive.Length);
            while (s.Connected)
            {
                string msg = "";
                int n = Signal(s, byteReceive);
                if (n == 0) { Array.Clear(byteReceive, 0, byteReceive.Length); continue; }
                msg = Encoding.UTF8.GetString(byteReceive);
                textBox2.Text += "n = " + n.ToString() + Environment.NewLine; // i use this to see if any byte that i could miss
                msg = msg.Replace("\0", "");
                string[] arrray_save = msg.Split('$');
                foreach (string message in arrray_save)
                {
                     //do my work
                }
                Array.Clear(byteReceive, 0, byteReceive.Length); continue;
            }
            try{s.Shutdown(SocketShutdown.Both); s.Close();}
            catch{}
     }
  }){isBackGround = true}.Start();       

I have suffered this for weeks :(, sorry for bad English, any help ill be appreciate.

Edited(05/24/2018) Here is my new code to make sure the data is correct to receive but the problem remains

byte[] data_save = new byte[1024]; int index = 0;
while (s.Connected)
            {
                int n = s.Available;
                if (n == 0) { continue; }
                byte[]byteReceive = new byte[n];
                s.Receive(byteReceive);
                byteReceive.CopyTo(data_save, index);
                index += byteReceive.Length;

                string test = Encoding.UTF8.GetString(data_save).Replace("\0", "");
                if (test[test.Length - 1] != '$') { continue; }
                textBox2.Text += test + Environment.NewLine;
                Array.Clear(data_save, 0, data_save.Length);
                index = 0;

                string[] array_save = test.Split('$');
                foreach (string message in array_save)
                {
                     //do my work
                }
         }try { s.Shutdown(SocketShutdown.Both); s.Close();} catch { }
Cœur
  • 37,241
  • 25
  • 195
  • 267
  • Check if client was still connected to the server. Most likely that's the case: server drops the connection with a client, client sends some confirmation but it never reaches server because connection was refused. – mrogal.ski May 23 '18 at 12:37
  • yes it still mate, thats why "+)Client still able to receive datas from Server" right? – Hiệp Nguyễn May 23 '18 at 12:40
  • You've wrote only 3 steps and the one you've posted above is the first one. I'm asking if there's no disconnect issue between step 1 and 2. Can you confirm that? Use debugger instead of wireshark. – mrogal.ski May 23 '18 at 12:46
  • i've edited a little bit of my problem, do you see any hint? – Hiệp Nguyễn May 23 '18 at 13:14

2 Answers2

2

This is not a correct socket read loop. You seem to be assuming that a single Receive() will always return a complete message. TCP/IP is a streaming protocol, and has no notion of messages. Each call to Receive may less than a whole message. Your server must know how many bytes it is expecting, or some indicator in the data to indicate when a complete message is recived. Also don't swallow the exceptions.

See eg

"One of the most common beginner mistakes for people designing protocols for TCP/IP is that they assume that message boundaries are preserved. For example, they assume a single “Send” will result in a single “Receive”."

Message Framing

David Browne - Microsoft
  • 80,331
  • 6
  • 39
  • 67
  • since the string message being sent uses the length-prefix means of identifying the string length they should reference the blog link found in the URL you provided above [https://blog.stephencleary.com/2009/04/sample-code-length-prefix-message.html]. – webmite May 23 '18 at 14:15
  • i might be get the point, looking into it; seen this post before but never think that whats causing my problem, thank you a bulk, lemme hug you – Hiệp Nguyễn May 23 '18 at 14:50
  • hey bros i come back with update, please take a look if you have time for me – Hiệp Nguyễn May 24 '18 at 11:40
  • Nope. That's still broken. How does your code determine that a complete message has been received? – David Browne - Microsoft May 24 '18 at 12:38
  • each of my message end with character "$". so i store the byteReceive in []data_save, if an Encoding shows me the message end with "$" that means i have received completed messages -> time to read them, else i keep collect more data for []data_save till i have enought to read – Hiệp Nguyễn May 24 '18 at 12:47
  • Does the client stop sending after the each '$'? – David Browne - Microsoft May 24 '18 at 12:55
  • nope, Client sends by my will and always successfully (caught by WireShark on Server's side) but server confirms it receives (n)bytes = 0 per loop since the problem happened. – Hiệp Nguyễn May 24 '18 at 13:03
  • I think you'd have to post a complete repro of both the client and the server for anyone to help more. – David Browne - Microsoft May 24 '18 at 13:27
0

in case someone would need, a thread for foreach and things solved.