Closing of c# socket by shutdown method - c#

I have a strange problem. I have client socket application which connects to server (client applications run on PCs and server application runs on server as windows service). Problem occurs in this code which is called on server for every opened client socket during closing of server application:
socket.Shutdown(SocketShutdown.Both);
socket.Close();
socket.Dispose();
Code runs without any error and application is closed successfully but problem will appear in client application immediatelly after server application close.
This is the code of async callback method which is registered by method BeginReceive on client:
private void ReadMachineServiceResponse(IAsyncResult ar)
{
int bytesRead = 0;
TcpServiceStateObject state = (TcpServiceStateObject)ar.AsyncState;
Socket handler = state.WorkSocket;
try
{
bytesRead = handler.EndReceive(ar);
}
catch (Exception ex)
{
bytesRead = 0;
this.Dispatcher.Invoke((Action)(() =>
{
this.AddEventLogMessage(LogMessageType.Error, ex.Message, null, true, false);
}));
}
try
{
if (bytesRead > 0)
{
//do some code...
}
state = new TcpServiceStateObject();
this._machineServiceSocket.BeginReceive(state.Buffer, 0, state.BufferSize, 0, new AsyncCallback(this.ReadMachineServiceResponse), state);
}
catch (Exception ex)
{
//do some exception code
}
}
When server application is closed then method ReadMachineServiceResponse is called several times in one second until client application is closed. It was called for two days until client application was closed by user. I discovered that this method is called even in case when I disconnect client computer from network - so problem is on client side. Messages that are received on client side after shutdown method call are empty - variable bytesRead = 0. Socket property "Connected" is still set to true. Client doesn't know that connection was closed so exception isn't thrown.
When I was try to comment line "socket.Shutdown(SocketShutdown.Both);" on server side then everything works correct. Exception was thrown on client side and any message wasn't received after closing of socket on server side.
Problem occurs everytime - it does not matter whether the client is connected to the server for a few seconds or several days, and whether the client receives some message from the server between the start and the end of the server run.
In netstat on client computer I can see that socket stays in CLOSE_WAIT state.
Thank you for every idea. I would like to know cause of this problem.

Related

How to know if the client call connection close on TcpListener?

I wrote simple application that using TcpListener.
The application is wait till some client will connect - and while the client is connected the application will listen to his sending stream.
In the code - i using while loop to check if the client is connected.
But event when i close the connection on the client side i get connected == true
But .. on the client close => i see that the server get byte stream with byte.length == 0
Code ...
private async void button1_Click(object sender, EventArgs e)
{
TcpListener tcpListener = new TcpListener(IPAddress.Any, 5501);
tcpListener.Start(1); // listen one client only
TcpClient client = await tcpListener.AcceptTcpClientAsync();
NetworkStream networkStream = client.GetStream();
while (client.Connected) // after connected => this is always true .. event if i close the connection on the client side
{
// do something ...
}
System.Console.WriteLine("No Connected");
}
TCP is a connection-oriented protocol, but the connection still is a virtual one - the only way to know that the other party is still connected is by successfully sending or receiving a message to/from it. This is why the Connected property may give false positives.
The 0-byte message means that the client has sent all their data and has closed (the send direction of) the socket. At that point the client still is connected, waiting for a 0-byte message back from the server (which is automatically sent when you close the server socket).
Of course in case of a network failure you would never receive that 0-byte message, but you would receive (eventually) a SocketException instead.
See this WinSock FAQ for more information about the shutdown process.

TCP Communication-Asynchronous Read Loop doesn't end

I am using Asynchronous TCP server/client communication. I have noticed in my log that the same client reconnects several times. However, it never shows that it was disconnected. My code has logging for both connection and disconnection. So why does readAsync stay in loop while the client has disconnected? Here is the code for your reference:
private async Task Accept(TcpClient client)
{
//get client information
string clientEndPoint = GetClientIPAddress(client);
log.Info("Client connected at " + clientEndPoint); //same client is connected several times in log
await Task.Yield ();
try
{
using (client)
using (NetworkStream stream = client.GetStream ())
{
byte[] dataReceived = new byte [100];
while (await stream.ReadAsync(dataReceived, 0, dataReceived.Length) != 0) //read input stream - 0=>end of stream is reached
{
//pass on data for processing
var task = ProcessData(dataReceived);
}
}
log.Info("Closing client connection " + clientEndPoint);//this line is never reached in log
if (client.Connected)
client.Close();
} //end try
catch (Exception ex)
{
log.Error(ex.Message);
log.Info("Closing client connection " + clientEndPoint);
if (client.Connected)
client.Close();
}
It looks like you may have a half-open problem. You should periodically write data to determine whether the socket is still connected; reads can detect graceful shutdowns but not half-open scenarios.
I describe the half-open problem more on my blog.
Did you check if TCP keep alive is set? That should detect if connection is broken.
Also, check if you got zero length bytes on receive, this means that connection is closed.
Edit: Keep Alive is standard method to check if connection is active, this means that one side sends small chunks of data to the other side periodically: http://en.wikipedia.org/wiki/Keepalive.
Many components have this feature already implemented. I've never used TcpClient class, but it must be some wrapper class for Socket over TCP and, as doc states, this class have exposed underlaying Socket (you can use Socket class for TCP also, but never mind). And this Socket have method SetSocketOption. So try:
client.Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive, true);

.Net Socket doesn't respond to remote disconnect?

I'm writing a small (C#) client application that sends data using a TCP/IP connection to a remote server. I'm using the standard .Net TcpClient object and want to leave the connection open from the client end as I am regularly submitting data packets to the server. However, it is possible that the server may close the connection, in which case I need to know to re-connect before sending my next packet.
Using Wireshark, I can see (only) the following dialogue when the server terminates the connection:
server >>> FIN, ACK ACK <<< client
What I do not see is my client responding with a FIN of its own, to complete the connection shutdown. The result is that my client program only finds out that the connection is down after sending the next data packet.
Is there any way I can set up TcpClient or its underlying Socket so as to complete the disconnect, and provide some feedback so that my client code knows to re-connect before sending the next packet?
Added in response to comment below:
My sending code is very simple - the object that maintains 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();
}
}
With m_client and m_outStream initialized, this simply performs a single pass every time. Then using Wireshark I can see the server send a packet with flags FIN, ACK to which the client responds with ACK.
The next time I call my function, the data is sent out with PSH, ACK, and the server responds with RST, ACK but does not read the incoming data. No exception is raised by the client.
Then I call my function a second time, and an exception is raised causing the connection to be re-started.
In general you should be able to use the Connected property on the TcpCient instance:
See here:
http://msdn.microsoft.com/en-us/library/system.net.sockets.tcpclient.connected.aspx
However:
Because the Connected property only reflects the state of the
connection as of the most recent operation, you should attempt to send
or receive a message to determine the current state. After the message
send fails, this property no longer returns true. Note that this
behavior is by design. You cannot reliably test the state of the
connection because, in the time between the test and a send/receive,
the connection could have been lost. Your code should assume the
socket is connected, and gracefully handle failed transmissions.
Try the following to make sure the Connected flag holds the most recent 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 a stream, at least there is no check in the .NET Framework TcpClient that prevents this. However it might not be aloud in the external code that is called from the framework to actually read from the network stream.
Be sure to Dispose of both the TcpClient and the Stream after your done, disposing the TcpClientdoes not dispose of the Stream so you need todo this manually, afterwards all resources are freed up (after GC).
From MSDN TcpClient.Connected property:
Type: System.Boolean
true if the Client socket was connected to a remote resource as of the most recent operation; otherwise, false.
This means, you would have to send some data to the server to detect the broken connection. Reading does not work, as you read from the buffer.
See my answer on a related question (https://stackoverflow.com/a/25680975/2505186),
linking the answer of someone else, where a suitable way is described to detect the connection status:
How to check if TcpClient Connection is closed?
Important for you:
The client does not close the connection automatically, when the server does so. The connection is in CLOSE_WAIT state then at the client side and in FIN_WAIT2 state at the server side. See the related section in the wikipedia article Transmission Control Protocol. Using the code from the linked answer above, you can detect that the connection is about to get closed. Further, you can finish the closing procedure then and reopen it if needed.
The method I use for detecting connected status is this one.
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 shutdown the connection, I call the following. Closing the underlying stream, and then the client object on top.
I enclose it in trys and catches to ensure that an attempt at closing them is attempted on each.
Note: PeerStream in this case is the 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)
{
}
}
I have found a partial answer to my question that solves the immediate problem.
While I still don't know if I can get my TcpClient to complete the disconnection, I can reliably discover whether 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
}

How can I unbind a socket in C#?

I'm having some problems reusing a server socket in a test application I've made. Basically, I have a program that implements both the client side and the server side. I run two instances of this program for testing purposes, one instance starts to host and the other connects. This is the listening code:
private void Listen_Click(object sender, EventArgs e)
{
try
{
server = new ConnectionWrapper();
HideControls();
alreadyReset = false;
int port = int.Parse(PortHostEdit.Text);
IPEndPoint iep = new IPEndPoint(IPAddress.Any, port);
server.connection.Bind(iep); // bellow explanations refer to this line in particular
server.connection.Listen(1);
server.connection.BeginAccept(new AsyncCallback(OnClientConnected), null);
GameStatus.Text = "Waiting for connections on port " + port.ToString();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
private void OnClientConnected(IAsyncResult iar)
{
try
{
me = Player.XPlayer;
myTurn = true;
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
GameStatus.Text = server.connection.RemoteEndPoint.ToString() + " connected";
StartServerReceive();
}
catch (Exception ex)
{
DispatchError(ex);
}
}
This works fine the first time. However, after a while (when my little game ends), I call Dispose() on the server object, implemented like this:
public void Dispose()
{
connection.Close(); // connection is the actual socket
commandBuff.Clear(); // this is just a StringBuilder
}
I also have this in the object constructor:
public ConnectionWrapper()
{
commandBuff = new StringBuilder();
connection = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
connection.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
}
I get no error when I click the Listen button a second time. The client side connects just fine, however my server side does not detect the client connection a second time, which basically renders the server useless anyway. I'm guessing it's connecting to the old, lingering socket, but I have no idea why this is happening to be honest. Here's the client connection code:
private void Connect_Click(object sender, EventArgs e)
{
try
{
client = new ConnectionWrapper();
HideControls();
alreadyReset = false;
IPAddress ip = IPAddress.Parse(IPEdit.Text);
int port = int.Parse(PortConnEdit.Text);
IPEndPoint ipe = new IPEndPoint(ip, port);
client.connection.BeginConnect(ipe, new AsyncCallback(OnConnectedToServer), null);
}
catch (Exception ex)
{
DispatchError(ex);
}
}
If I do netstat -a in CMD, I see that the port I use is still bound and its state is LISTENING, even after calling Dispose(). I read that this is normal, and that there's a timeout for that port to be "unbound".
Is there a way I can force that port to unbind or set a very short timeout until it automatically gets unbound? Right now, it only gets unbound when I exit the program. Maybe I'm doing something wrong in my server? If so, what could that be? Why does the client connect fine, yet the server side doesn't detect it a second time?
I could make the socket always listen, not dispose it, and use a separate socket to handle the server connection, which would probably fix it, but I want other programs to be able to use the port between successive play sessions.
I remember seeing another question asking this, but there was no satisfactory answer for my case there.
There may be a couple of reasons why the port would stay open, but I think you should be able to resolve your issue by using an explicit LingerOption on the socket:
LingerOption lo = new LingerOption(false, 0);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);
This basically turns the socket shutdown into an abortive shutdown instead of a graceful shutdown. If you want it to be graceful but just not wait as long, then use true in the constructor and specify a small but nonzero value for the timeout.
I just noticed this line, which is almost undoubtedly part of your problem:
server.connection = server.connection.EndAccept(iar); // I will only have one client, so I don't care for the original listening socket.
The comment you've written here is, well, wrong. Your wrapper class really shouldn't allow connection to be written to at all. But you cannot simply replace the listening socket with the client socket - they're two different sockets!
What's going to happen here is that (a) the listening socket goes out of scope and therefore never gets explicitly closed/disposed - this will happen at a random time, possibly at a nasty time. And (b) the socket that you do close is just the client socket, it will not close the listening socket, and so it's no wonder that you're having trouble rebinding another listening socket.
What you're actually witnessing isn't a socket timeout, it's the time it takes for the garbage collector to realize that the listening socket is dead and free/finalize it. To fix this, you need to stop overwriting the listening socket; the Dispose method of your wrapper class should dispose the original listening socket, and the client socket should be tracked separately and disposed whenever you are actually done with it.
In fact, you should really never need to rebind another listening socket at all. The listening socket stays alive the whole time. The actual connection is represented by just the client socket. You should only need to dispose the listening socket when you finally shut down the server.
I agree with the previous answer, you should also "shutdown" to allow any existing activity to complete and then close the socket flagging it for reuse...
socket.Shutdown(SocketShutdown.Both);
socket.Disconnect(true);

Determining if .NET socket is currently connected bug?

I'm trying to find out whether a Socket is currently connected - according to the MSDN docs for Socket.Connected - I should do the following:
// This is how you can determine whether a socket is still connected.
bool blockingState = client.Blocking;
try
{
byte [] tmp = new byte[1];
client.Blocking = false;
client.Send(tmp, 0, 0);
Console.WriteLine("Connected!");
}
catch (SocketException e)
{
// 10035 == WSAEWOULDBLOCK
if (e.NativeErrorCode.Equals(10035))
Console.WriteLine("Still Connected, but the Send would block");
else
{
Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode);
}
}
finally
{
client.Blocking = blockingState;
}
Console.WriteLine("Connected: {0}", client.Connected);
I've tested this works by connecting the socket to a remote server running on Windows and killing the remote server and it works fine.
However, if I do the same with a remote Server running on Unix (in this case MAC OS X) then the code does not work - the client.Send(tmp, 0, 0) call completes without throwing an exception and prints "Connected: true".
I'm guessing this has something to do with the fact that the other side of the connection has closed so the send may still work but a receive would fail - can I do a zero-byte Receive or something to see if the socket is closed?
Yes, you can.
Calling Send only really checks if the local socket is open. Calling Receive will check the other end too.
Maybe you can sniff with Wireshark the traffic and see if there are any difference if the dying server side is a windows or unix system.
Maybe the dying windows system is able to send a tcp close while the unix system can't. That would explain the difference (but maybe not help your actual problem).
btw, if you would use a udp connection you could never determine if the other site is living, due to the fact this would be a send & forget communication.

Categories