C # client / server Question

I am incredibly confused what is going on here. I set the break points, and I just canโ€™t understand. Basically, I have a client and a server. I want the client to send two separate rows of data. From entering breakpoints, I noticed that my client really fills both lines with the appropriate data. However, the server never sees the second line. Why is this happening and how can I fix it? Any help at all would be greatly appreciated! Below is my code:

Server:

private static void HandleClientComm(object client) { /** creating a list which contains DatabaseFile objects **/ List<DatabaseFile> theDatabase = new List<DatabaseFile>(); TcpClient tcpClient = (TcpClient)client; NetworkStream clientStream = tcpClient.GetStream(); StringBuilder response = new StringBuilder(); byte[] message = new byte[4096]; int bytesRead; do { bytesRead = 0; try { /*do { bytesRead = clientStream.Read(message, 0, message.Length); response.Append(Encoding.ASCII.GetString(message, 0, bytesRead)); } while (clientStream.DataAvailable);*/ 

when I change this commented code to bytesRead = clientStream.Read (message, 0, 4096); I get an IOException error that reads as follows: Unable to write data to the transport connection: The existing connection was forcibly closed by the remote host. Therefore, I changed it to a while loop. How to get around this IOException and accept the second line?

  ASCIIEncoding encoder = new ASCIIEncoding(); String file = encoder.GetString(message, 0, bytesRead); Menu.Insert(theDatabase, file); } catch (Exception) { // A socket error has occured break; } if (bytesRead == 0) { // The client has disconnected from the server break; } } while (clientStream.DataAvailable); // Release connections clientStream.Close(); tcpClient.Close(); } 

Customer:

  static void Main(string[] args) { TcpClient client = new TcpClient(); IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8888); client.Connect(serverEndPoint); NetworkStream clientStream = client.GetStream(); NetworkStream clientStream2 = client.GetStream(); ASCIIEncoding encoder = new ASCIIEncoding(); ASCIIEncoding encoder2 = new ASCIIEncoding(); String text = System.IO.File.ReadAllText("FirstNames.txt"); String text2 = System.IO.File.ReadAllText("LastNames.txt"); byte[] buffer = encoder.GetBytes(text); Console.ReadLine(); clientStream.Write(buffer, 0, buffer.Length); clientStream.Flush(); Console.ReadLine(); byte[] buffer2 = encoder2.GetBytes(text2); clientStream2.Write(buffer2, 0, buffer2.Length); clientStream2.Flush(); Console.ReadLine(); } } 
+4
source share
3 answers

The connection between the client and the server is as follows (note that the order of steps is for illustration only, the actual order at run time may be different):

  • Client: client.Connect(serverEndPoint)
    Server: HandleClientComm(newClient)

  • Client: clientStream.Write(buffer, 0, buffer.Length)
    Server: bytesRead = clientStream.Read(message, 0, message.Length)
    Please note that Read cannot read the whole message. It is perfectly normal to return only the part received so far

  • Client: Console.ReadLine()
    Server: while (clientStream.DataAvailable)
    There is no data in the stream - the client did not send them. This will probably happen even without ReadLine - a time window will appear before the client sends the data again

  • Server: tcpClient.Close()

  • Client: clientStream2.Write(buffer2, 0, buffer2.Length)
    You can get an exception here or not - depending on whether the server has already closed the connection, in any case, the server no longer reads.

You need to define your own message protocol that will be executed by both the server and the client. For example, you can close the client when it is sent:

Customer:

 using (var client = new TcpClient("localhost", 8888)) using (var clientStream = client.GetStream()) { var buffer = Encoding.ASCII.GetBytes( File.ReadAllText("FirstNames.txt") ); clientStream.Write(buffer, 0, buffer.Length); buffer = Encoding.ASCII.GetBytes( File.ReadAllText("LastNames.txt") ); clientStream.Write(buffer, 0, buffer.Length); } 

Server:

 using (var tcpClient = (TcpClient)client) using (var clientStream = tcpClient.GetStream()) { // Store everything that the client sends. // This will work if the client closes the connection gracefully // after sending everything var receivedData = new MemoryStream(); clientStream.CopyTo(receivedData); var rawBytes = receivedData.ToArray(); var file = Encoding.ASCII.GetString(rawBytes, 0, rawBytes.Length); Menu.Insert(theDatabase, file); } 

The protocol is simple and may be enough for your case. However, there are problems with it that need to be fixed in the production code (for example, if the client sends too much data, exhausting the serverโ€™s memory, what if the client stops sending without closing the connection, etc.)

+2
source

since while (clientStream.DataAvailable) no longer true after the first call to the client.

+2
source

You exit the client-recv loop on your server just because DatAvailable is false. This means that if the client was supposed to send a data frame (which you are consuming) and pause, then your server will not see any data at that moment and will be disconnected even if another data frame from the client in occurs in a second. Almost always, the end of the dialogue is based on the contents of the transmitted data. Of course, you can never count on a DataAvailable to be false once.

As a continuation, if you provide more information about the protocol used, we can give more information. For example, if the proto-thread is that two lines are sent with CR / LF at the end, then the server loop should check the buffer to know when to turn it off.

+1
source

All Articles