Reputation: 2556
I'm having problems sending a very small piece of data (a date) to another TcpClient running on the same computer.
In the code below you will see that it sleeps before closing the NetworkStream. If I remove the Sleep
it causes an intermittent problem where the data doesn't turn up at the other end.
Am I doing something wrong here?
using (TcpClient client = new TcpClient())
{
client.Connect(new IPEndPoint(IPAddress.Loopback, _tcpServerPort));
NetworkStream clientStream = client.GetStream();
byte[] buffer = new ASCIIEncoding().GetBytes(theDateObject.ToString("yyyy-MM-dd HH:mm:ss"));
clientStream.Write(buffer, 0, buffer.Length);
clientStream.Flush();
System.Threading.Thread.Sleep(1000); // Remove this line and the data may not arrive at the other end
clientStream.Close();
}
Some other information:
Sleep
without it causing a problem (slower computers perhaps?)Close(int timeout)
(instead of sleeping) but that didn't help.Upvotes: 1
Views: 1582
Reputation: 1926
If your receive queue is not empty (you got data in your receive buffer from the server that you haven't read, disposing the Socket (Client) sends a TCP RST (Resets the connection)) and the data in the send buffer is discarded i.e if not already sent lost, otherwise it waits till the send buffer is empty and then terminates the tcp connection.
One workaround is to close the send channel:
client.Client.Shutdown(SocketShutdown.Send)
clientStream.Close();
}
before closing the client (instead of thread.sleep), in this case the conneciton is not reset.
Also .Flush() does nothing on a networkstream.
see: http://cs.baylor.edu/~donahoo/practical/JavaSockets/RecvQClose.pdf
Upvotes: 0
Reputation: 15130
Calling close with a timeout on a NetworkStream means that the network stream will stay open in the background for X time to allow remaining data to be sent. In the background is important to note since your code is not blocked by this. Because you encapsulate the tcpClient in a using statement, the client and internally the NetworkStream will be disposed directly after your call to close. Sleep in this case works since it allows the data to be sent out and blocks your method in the meantime to prevent it from forcefully disposing of its resources.
A cleaner solution would be to set an active LingerState on the TcpClient with a long enough timeout. See: http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.lingerstate.aspx
Upvotes: 1