Click here to Skip to main content
15,888,025 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi,

I wrote a client/server application, I used TcpServer an TcpClient objects to enable this communications.

Server side I had no problem. It seems that when the client perform a request, the server reply so quickly. But Client side there is a little slowdown at the TcpClient initialization.

How use a single TcpClient initialization for all requests?

Thank you!

What I have tried:

I wrote this method:
C#
TcpClient TcpClient = null;
NetworkStream TcpClientStream = null;
public string SendRequest(string command, out string response)
{
   TcpClient = new TcpClient(TcpAddress, TcpPort);      // [1]
   TcpClientStream = TcpClient.GetStream();             // [2]
   byte[] msg = Encoding.ASCII.GetBytes(command);
   TcpClientStream.Write(msg, 0, msg.Length);
   byte[] result = new byte[0];
   msg = new byte[TcpClient.ReceiveBufferSize];
   int i;
   while ((i = TcpClientStream(Read(msg, 0, msg.Length)) > 0)
   {
      Array.Resize(ref result, result.Length + i);
      Array.Copy(msg, 0, result, result.Length - i, i);
   }
   TcpClientStream.Close(); TcpClientStream = null;     // [3]
   TcpClient.Close(); TcpClient = null;                 // [4]
   return Encoding.ASCII.getString(result);
}


Result: Every time the TcpClient is initialized ([1]) there is a slowdown of about a second.
I tried to leave the TcpClient open replacing that statement with:
C#
if (TcpClient == null)
   TcpClient = new TcpClient(TcpAddress, TcpPort);

and commenting the [4] statement, but the [2] throws an InvalidOperationException (socket not connected).
I tried to check if it was not connected just after [1]:
if (!TcpClient.Connected)
   TcpClient.Connect(TcpAddress, TcpPort);

The TcpClient.Connected is false, but the Connect method throws a SocketException (socket already connected)
I tried also to leave the TcpClientStream open commenting [3] and replacing [2] with:
C#
if (TcpClientStream == null)
   TcpClientStream = TcpClient.GetStream();

and this seems to run better. The TcpClientStream.Write is executed normally and without any slowdown, but the server doesn't receive the message.
Posted
Updated 4-Sep-16 23:45pm

It might be better putting this in the discussions rather than Q&A, as I don't think there's a clear answer, but lots which could be said.

Firstly, if line [1] is taking a second to execute, that's how long it takes to do the DNS lookup on the hostname and establish the TCP connection. Seems like a long time, but it is possible. If this is the case then you probably will want to keep the connection alive for multiple uses.

You might find that attaching a StreamReader and StreamWriter to the network stream makes life easier - you can set the encoding on the constructors and these will take care of the buffering for you (avoiding the somewhat hideous array resizing). It'll be a bit like reading/writing to the console with those. Make sure you flush the writer when you want to send the data.

The problem with reusing the connection seems to be in the protocol itself, that is you take a string and turn it into ASCII encoded bytes and fire it down the wire - there is no obvious delimiter to say when you are done. This means the server doesn't really know when to stop reading from the socket - just because there is no data there doesn't necessarily mean the end. You'd expect at least a new line or something to signal the end of transmission.

Similarly on the receiving end, I believe you just keep on reading until there is no more data there - Read returns <= 0. This means it will keep on reading or blocking there until the connection is closed, so without some sort of delimitation you cannot reuse the connection.

If you get small delays, its worth reading up on the Nagle Algorithm.

Also, it's good practice to shutdown the socket prior to closing it. This helps bring about a graceful end to the communication. Generally, you don't need it but I have seen occasional problems without it.
 
Share this answer
 
[1]: no, i think not. It needs a second also if I use 127.0.0.1 as the address.

For the other your points, I followed your sudgestions. But not for the ASCII encoded. There are more than a single path I have to follow, some times I don't receive a ASCII string. Then the server writes the lenght of the data and the rest of the data, Then the client read the lenght of the data and wait for exactly that number of bytes.

Thank you
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900