I have a .NET windows service that uses an open source library (Asterisk.net - C#) to listen to TCP connections on a specific port.
This service is deployed on a number of VM instances of Windows 7 (all from the same source image). The connections all come from the VM host (centos). On one (and only one) of these instances the ACK response from windows to the connecting client is delayed by three seconds on the occasional incoming connection. Other times, the ACK is sent immediately.
This delay causes the client to time out:
I'm no expert at TCP sockets, but it seems from a debug that these ACKs are sent before the connection is handed to the app (or in this case library), and even if the accepting thread is blocked, so it is a problem at the windows or .net library level?
The code that handles the inbound connections quickly hands it off to a thread and returns.
public IO.SocketConnection Accept()
{
if (tcpListener != null)
{
TcpClient tcpClient = tcpListener.AcceptTcpClient();
if (tcpClient != null)
return new IO.SocketConnection(tcpClient, encoding);
}
return null;
}
So, what could be causing this infuriating delay? What am I missing?
These 3 packets you recorded are the establishing of the connection. See https://en.m.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment.
However, if it happens only in 1 VM, then it's no programming issue. Try loading the VMs in different order, check firewall settings etc.
Also, test with a network terminal software like HWGroup Hercules and monitor the connections using Sysinternals TCPView.
Related
We have been developing a .NET Framework 4.6.1 app with C# that has as one of its tasks to send NMEA 0183 sentences to a multiplexer via local area network connection (Wi-Fi or Ethernet). The app can be configured to connect using TCP or UDP. The communication between the app and the multiplexer works over UDP for hours without any problems, but TCP connection has this problem that a ShipModul's multiplexer that I have been using in my own testing scenarios forcibly closes the connection after about 10 or 15 minutes. Also, other users of the app have confirmed that other multiplexers might not work at all when the app is configured to use TCP, but that UDP connection still works without a problem. The communication is one-way from the .NET Framework app to multiplexer.
What might be the reason for the premature closing of the TCP connection? Is there some requirement and mechanism to actively keep the connection alive, and not just that it is assumed to be alive when IP packets arrive from the PC? And if the connection needs to be actively maintained, then how you do it with .NET TcpClient object?
Simplyt put, the code is something like (executed only when using TCP):
// connection initilization
tcpClient = new TcpClient(new IPEndPoint(unicastAddress.Address, port));
tcpClient.Connect(ipAddress, port);
networkStream = tcpClient.GetStream();
// ..prepare the NMEA sentence data..
networkStream.Write(asciiEncodedNmeaData, 0, asciiEncodedNmeaData.Length);
The corresponding UDP protocol version of the code (executed only when using UDP):
// connection initialization
udpClient = new UdpClient(new IPEndPoint(unicastAddress.Address, port));
udpClient.Connect(ipAddress, port);
// ..prepare the NMEA sentence data..
udpClient.Send(asciiEncodedNmeaData, asciiEncodedNmeaData.Length);
Also, when the app is closed/paused, the Close() method is called on either of the above client object depending on which protocol is used (and everything restarts as above when the app is unpaused):
tcpClient.Close();
networkStream.Close();
or:
udpClient.Close();
Then, after about 15 minutes there appears this exception:
System.IO.IOException: 'Unable to write data to the transport connection: An existing connection was forcibly closed by the remote host.'
It's a standard situation. TCP connection is stateful, i.e. consumes finite resources like memory. That's why network equipment usually discards inactive connections. In your case connection is considered idle "after about 10 or 15 minutes".
To avoid this, you can send "keep alive packets". Just write any data (the less the better) to networkStream by timer, e.g. every 5 minutes.
Existing scenario is explained below.
Our application is running on Client Server architecture; Client is developed with VC++ and Server is developed with C#.
On the Server side there are two exe's running (myServer1.exe -Windows service based, and myServer2.exe -Windows application). myServer2.exe is communicating to myServer1.exe through TCP socket connection.On the Client side, an exe (myApp1.exe -Windows Service based) runs another exe based on user sessions present in the machine (myUser.exe for all user sessions). Every myUser.exe instances are communicating to myApp1.exe through PIPE communication. And myApp1.exe is also communicating to myServer1.exe through another TCP communication.
New scenario.
We are now creating a TCP socket in listening mode in myServer2.exe (Server application -C#). myUser.exe (Client application -VC++) is trying to connect to myServer2.exe through a TCP connection by using CAsyncSocket. But the framework calls (OnConnect, OnReceive and OnClose) are not happening.
Socket creation- Create(0,SOCK_STREAM); // CAyncSocket
Socket connection- Connect("ServerIP", "ServerPort"); // CAsyncSocket
Note: when we move the socket creation and connection functionalities into Windows service based exe (myApp1.exe), the connection works fine, OnConnect OnReceive and OnClose are happening.
Why framework call to OnConnect is not happening in myUser.exe while in myApp1.exe is?
Your OnConnect method is not called because probably you don't have the message loop in myUser.exe while you have it in myApp.exe.
Error code 10035 is WSAEWOULDBLOCK and it' normal for your case, from MSDN:
It is normal for WSAEWOULDBLOCK to be reported as the result from
calling connect on a nonblocking SOCK_STREAM socket, since some time
must elapse for the connection to be established.
So don't worry about it. If you have a message loop, after your Connect call, the OnConnect method will finally be called at a certain time with a successful result or with an error code.
See also codeproject and SO
Let's say we have a basic TCP server with a .NET TcpListener, with a basic TCP client using a .NET TcpClient.
What types of connection terminations are there, and how are they supposed to be checked for and handled?
Client
A. Client gracefully terminates the connection. The server is notified.
B. Client physically disconnects from the network. How does the server know?
C. Client program shuts down without a graceful disconnect. How does the server know?
Server
A. Server gracefully terminates the connection. The client is notified.
B. Server physically disconnects from the network. How does the client know?
C. Server program shuts down without a graceful disconnect. How does the client know?
Cases A and C are communicated by a TCP packet with the FIN flag set in the header. It is sent by the TCP/IP stack in the OS, so it doesn't matter if the application exited abnormally. The subcase of C where the OS also failed will act like B instead.
Case B, when you've lost the ability to communicate, is more complicated. If the failure is local (e.g. disassociation from a WiFi access point), then the local end of the connection will find out immediately about a change in network status, and can infer that the connection is broken (but if not cleaned up, a connection can survive a short-term outage).
If the connections are actively transmitting data, the acknowledgements will timeout and result in retransmission attempts. A limit may be placed on retransmission attempts, resulting in an error.
If there is no traffic, then it is possible for loss of connection to go undetected for a very long time (multiple days). For this reason, TCP connections often are configured to send heartbeat packets, which must be acknowledged, and detect failure of retransmission attempts in the same manner as normal data.
The short answer is: neither knows instantly when the other disconnects. UNTIL of course something lets you know.TCP isn't a physical connection therefore it relies on signals of some sort to determine the state. Usually either by checking the connection or receiving a graceful disconnect message from the other side. There are various ways to check for connections (polling, timeouts, catching socket exceptions, etc). It really depends on framework you're using and what your needs are.
If you have the resources to poll, then you can poll ever x seconds and check the state. Etc.
Check this extension method found here.
static class SocketExtensions
{
public static bool IsConnected(this Socket socket)
{
try
{
return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
}
catch (SocketException) { return false; }
}
}
Basically, socket.Poll() returns true if the connection is open and there is data, or it will return true if there is no connection. socket.Available will return the number of bytes being sent. If it's 0, && .Poll() was true, then the connection is effectively closed. It gets confusing if you try to follow the true/falses, but this will return with pretty good accuracy.
I have a TCP socket based client server system.
Everything works fine but when network is disconnected form client end and reconnect it again i get automatically SocketError.ConnectionReset send form client and regarding this command the socket is closed in the server side. this is also fine.
but when i look in to the client side it shows the socket is still connected with server. (regarding socket is still connected with server [It does not happen every time], sometime it shows disconnected and some times shows connected)
Does it make sense that "server get a SocketError.ConnectionReset from
client end but client is still connected"?
So i want to know what is the possible reasons of SocketError.ConnectionReset and how to handle such type of problem i have mentioned?
Again i say, Everything is working fine in normal environment (e.g if i exit the client it is disconnected the socket same for the server)
Thanks in advance.
EDIT:
Here is the code in the client side. actually it's a timer that tick every 3 second through programs lifetime and check if Socket is connected or not if its disconnected then it tries to reconnect again through a new socket instance
private void timerSocket_Tick(object sender, EventArgs e)
{
try
{
if (sck == null || !sck.Connected)
{
ConnectToServer();
}
}
catch (Exception ex)
{
RPLog.WriteDebugLog("Exception occcured at: "+ System.Reflection.MethodBase.GetCurrentMethod().ToString()+"Message: "+ex.Message);
}
}
In normal situation (without network disconnect/reconnect) if TCP server get a
SocketError.ConnectionReset form any client, in the client side i see
clients socket is disconnected and it tries to reconnect it again
through the code shown. but when situation happen explained earlier,
server gets a SocketError.ConnectionReset but client shows it still
connected. though the TCP server shows the reset command is send form the exact client
side.
There are several causes but the most common is that you have written to a connection that has already been closed but he other end. In other words, an application protocol error. When it happens you have no choice but to close the socket, it is dead. However you can fix the underlying cause.
When discussing a TCP/IP issue like this, you must mention the network details between the client and the server.
When one side says the connection is reset, it simply means that on the wire a RST packet appears. But to know who sends the RST packet and why, you must utilize network packet captures (by using Wireshark and any other similar tools),
https://en.wikipedia.org/wiki/Transmission_Control_Protocol
You won't easily find out the cause at .NET Framework level.
The problem with using Socket.Connected as you are is that it only gives you the connected state as at the last Send or Receive operation. i.e. It will not tell you that the socket has disconnected unless you first try to send some data to it or receive data from it.
From MSDN description of the Socket.Connected property:
Gets a value that indicates whether a Socket is connected to a remote host as of the last Send or Receive operation.
So in your example, if the socket was functioning correctly when you last sent or received any data from it, the timerSocket_Tick() method would never call ConnectToServer(), even if the socket was now not connected.
how to handle such type of problem i have mentioned?
Close the socket and initiate a new connection.
I've created an asynchronous server in C# to go along with my Android application. The server is similar to this: http://msdn.microsoft.com/en-us/library/fx6588te.aspx
It works well and I can have many clients connect and receive data from the server at the same time. One problem that I've found is that in my Android app if you are already connected over Wifi and press the connect button again, the server spawns a new socket. The server should kill the old connection first and then create a new connection. On the Android side I make sure to call close() and even set it to null afterwards. I also send a disconnect control signal to the server so that it can also call close() on the socket. For example, here's how I do it in the server:
if (state.storage.parseJson(content) == JsonStorage.DISCONNECT)
{
Console.WriteLine("Disconnect2!");
state.workSocket.Shutdown(SocketShutdown.Both);
state.workSocket.Close();
return;
}
When I inspect my server process in a program called "CurrPorts" it shows several connections open to my Android device on different ports. I send data to my clients using a Timer object, and I also check to see if the connection is active otherwise I close it. For example, my TimerCallback method:
public void TimeCallBack(object input)
{
StateObject state = (StateObject)input;
if (state.workSocket.Connected)
{
Send(state.workSocket, state.storage.getJson());
}
else
{
Console.WriteLine("Dispose!");
state.timer.Dispose();
state.workSocket.Close();
}
}
I can't think of why my server isn't closing old connections. There should only be as many connections open as devices connected to the server. If this were a threaded blocking server then it would be easy to just close the thread down, but I'm not sure what to do in this case.
edit: so I just refreshed the CurrPorts program after letting it sit for a while and it dropped down to one established connection. Is my solution right and it just takes a while for Windows to actually clear the old socket connections that were created?
Yes, Windows will keep around the information about the socket for a while. You can see this with netstat, closed sockets will show a state of TIME_WAIT after they are closed and even after the application that hosted the socket has terminated.