.Net socket not responding remotely disconnect?

I am writing a small (C #) client application that sends data using a TCP / IP connection to a remote server. I use the standard .Net TcpClient object and want to leave the connection open from the end of the client, as I regularly send data packets to the server. However, it is possible that the server might close the connection, in which case I need to know how to reconnect before sending the next packet.

Using Wireshark, I see (only) the following dialog when the server terminates the connection:

server >>> FIN, ACK
ACK <<< client

What I don't see is my client, which responds with its own FIN to complete the connection. As a result, my client program detects that the connection was not sent after sending the next data packet.

Is it possible to configure TcpClient or its underlying Socket to complete the disconnection and provide some feedback so that my client code knows I need to reconnect before sending the next packet?

Added in response to the comment below: My submit code is very simple - an object that supports the TcpClient and NetworkStream member variables has a member function containing (essentially) the following:

 bool sent = false; byte[] buffer = Encoding.UTF8.GetBytes(dataString); while (!sent) { try { m_outStream.Write(buffer, 0, buffer.Length); sent = true; } catch (Exception ex) { if (m_outStream != null) { m_outStream.Dispose(); } m_client = new TcpClient(AddressFamily.InterNetwork); m_client.Connect(ipAddress, ipPort); m_outStream = m_client.GetStream(); } } 

When initializing m_client and m_outStream, it simply performs one pass each time. Then, using Wireshark, I see how the server sends a packet with FIN, ACK flags, to which the client responds with ACK .

The next time my function is called, the data is sent using PSH, ACK , and the server responds with RST, ACK , but does not read the incoming data. The client does not raise any exceptions.

Then I call my function a second time, and an exception is raised causing the connection to restart.

+4
source share
4 answers

In general, you should be able to use the Connected property in an instance of TcpCient :

Look here:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx

However:

Since the Connected property reflects only the state of the connection with the last operation, you should try to send or receive a message to determine the current state. After the send failed message, this property no longer returns true. Please note that this is a design behavior. You cannot reliably check the status because, between the test and the send / receive, the connection could be lost. Your code should accept the connector plugged in and gracefully handles failed transfers.

Try the following to verify that the Connected flag contains the last state:

 var tcpClient = new TcpClient (); tcpClient.Connect(); var stream = tcpClient.GetStream(); // buffer size need to be > 0 int[] buffer = new int[1]; stream.Read(buffer, 0, 0); if(!tcpClient.Connected) // do something 

Based on decompilation, it should be possible to read 0 bytes from the stream, at least there is no check in the .NET Framework TcpClient that prevents this. However, this may not be aloud in the external code that is called from the framework to actually read from the network stream.

Be sure to Dispose both TcpClient and Stream after execution, disposing of TcpClient does not delete Stream , so you need to do this manually, after which all resources will be freed (after GC).

+4
source

From the MSDN TcpClient.Connected property:
Type: System.Boolean
true if the client socket has been connected to the remote resource since the most recent operation; otherwise false.

This means that you will need to send some data to the server in order to detect a failed connection. Reading does not work as you read from the buffer.

See my answer on the relevant question ( https://stackoverflow.com/a/25680975/2505186 )
linking the response of another user, which describes the appropriate way to determine the status of the connection: How to check if the TcpClient connection is closed?

Important for you:
The client does not close the connection automatically when the server does this. The connection is in CLOSE_WAIT state, and then on the client side and FIN_WAIT2 on the server side. See the relevant section in the wikipedia article Transmission Control Protocol . Using the code from the linked answer above, you may find that the connection will be closed. Alternatively, you can end the closing procedure and then open it again.

+3
source

The method that I use to detect connection status is this.

 static class SocketExtensions { /// <summary> /// Extension method to tell if the Socket REALLY is closed /// </summary> /// <param name="socket"></param> /// <returns></returns> public static bool IsConnected(this Socket socket) { try { return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0); } catch (SocketException) { return false; } } } 

When I want to end the connection, I call the following. Closing the main thread, and then the client object on top. I am attaching it to attempts and catches in order to try to close them. Note: PeerStream in this case is NetworkStream (from Client.GetStream ())

 /// <summary> /// Method will disconnect this peer forcefully /// </summary> public void Disconnect() { try { PeerStream.Close(); } catch (Exception ee) { } try { _client.Client.Disconnect(false); } catch (Exception ee) { } } 
+1
source

I found a partial answer to my question that solves an immediate problem.

While I still don't know if I can terminate TcpClient to complete the disconnect, I can reliably find out if the socket has disconnected using the following code:

 if (m_client.Client.Poll(1000, SelectMode.SelectRead) && (m_client.Client.Available == 0)) { // Connection has gone - reconnect! m_client = new TcpClient(AddressFamily.InterNetwork); m_client.Connect(ipAddress, ipPort); } else { // Connection is good, nothing to do } 
0
source

Source: https://habr.com/ru/post/1401147/


All Articles