Client socket cannot connect but does not throw an SocketException - c#

My asynchronous connect code is very rudimentary and is as followed:
private Socket _socket;
public void Connect(IPEndPoint remoteEndPoint, bool persistentConnection)
{
_logger.Trace("Attempting To Connect To " + remoteEndPoint.Address);
_remoteEndPoint = remoteEndPoint;
_persistentConnection = persistentConnection;
_socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
_socket.BeginConnect(_remoteEndPoint, ConnectCallback, null);
}
The Connect() method is accompanied by ConnectCallback() which is the where the problem I will describe shortly occurs:
private void ConnectCallback(IAsyncResult asyncResult)
{
try
{
_socket.EndConnect(asyncResult);
_logger.Trace("Successfully Connected To " + _remoteEndPoint.Address);
}
catch (SocketException)
{
_logger.Trace("Failed To Connect To " + _remoteEndPoint.Address);
if (_persistentConnection)
{
Thread.Sleep(TimeSpan.FromSeconds(3));
Connect(_remoteEndPoint, true);
return;
}
}
_socketWriter.AssignSocket(_socket);
_socket.BeginReceive(..);
}
My networking code is encapsulated within a single assembly. Today I decided to reference the assembly from another applications and found the ConnectCallback method to behave very oddly.
I make a call to Connect() when the server application is not running. This means it is not physically possible for the connection to succeed. Because the remote end point is not available, I would expect EndConnect to throw an exception. Instead EndConnect appears to succeed because even though the socket is not really connected, my code proceeds to make a call to _socket.BeginReceive which of course, throws an exception because the socket is not connected.
What is especially bizarre is that if I place a break point on the opening try brace and step-through the call back code the exception is thrown and handled.
This happens on local host.
Why am I experiencing this behaviour and how can I ensure that EndConnect throws a SocketException is the connection cannot established consistently?

You only return from the catch if _persistentConnection is true. If not, you call BeginReceive() anyway.

Related

How to Dispose a Socket after ConnectAsync times out? [duplicate]

I feel, that I am misunderstanding something about async sockets in .Net. The situation is as follows : I have 1 async socket client and 1 async socket server. They communicate without any visible problems, but when I close listener and disconnect clients, the "OnConnectRequest" which is bound to "BeginAccept" as a callback, still gets called at least once. The "BeginReceive", "OnConnectRequest", "Disconnect" and "Dispose" methods are :
public void BeginReceive()
{
_listener.Bind(_endpoint);
_listener.Listen(_maxConnections);
try
{
_listener.BeginAccept(new AsyncCallback(OnConnectRequest), _listener);
}
catch (SocketException se)
{
OnListeningError(this, new Exception("Server cannot accept connections due to network shutdown or some fatal failure", se));
}
}
protected void OnConnectRequest(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket client = listener.EndAccept(ar);
var remoteEndpoint = client.RemoteEndPoint;
IDuplexStateObject state = new DuplexStateObject();
state.WorkSocket = client;
if (_clients.Count <= _maxConnections)
{
lock (_clients)
{
_clients.Add(state);
}
OnConnected(this, state);
}
else
{
//denying connection
client.Close();
AcceptingError(this, null, new Exception(string.Format("Maximal connection count reached, connection attempt {0} has been denied", (remoteEndpoint != null) ? remoteEndpoint.ToString() : null)));
}
//accept connections from other clients
try
{
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
}
catch (SocketException se)
{
if (se.SocketErrorCode == SocketError.TooManyOpenSockets)
{
OnListeningError(this, new Exception("Maximal connection count reached, not possible to create any more connections"));
}
else
{
OnListeningError(this, new Exception("Server cannot accept connections due to network shutdown or some fatal failure"));
}
}
}
public void Disconnect(IStateObject state)
{
if (state.WorkSocket == null)
{
//OnDisconnectError(this, state.ClientInfo,
// new Exception("No underlying work socket found for client. Already disconnected, disposing connection..."));
OnDisconnected(this, state.ClientInfo);
return;
}
try
{
if (state.WorkSocket.Connected)
{
state.WorkSocket.Shutdown(SocketShutdown.Both);
}
state.WorkSocket.Close();
}
catch (SocketException se)
{
OnDisconnectError(this, state.ClientInfo, se);
}
OnDisconnected(this, state.ClientInfo);
lock (_clients)
{
_clients.Remove(state);
}
}
public void Dispose()
{
_listener.Close();
//keys are cloned before disconnecting
foreach (var client in _clients.ToList())
{
Disconnect(client);
}
}
What I am doing is calling "Dispose" to closes listener and shut down all client sockets. The client is then still active, and it tries to reconnect, but what I expected to happen was server being completely unavailable on corresponding IP and port. What I see instead is "OnConnectRequest" callback being called, which crashes because of attempt to use already disposed socket. Can you please explain, what is wrong here, and how graceful shutdown of a listener and all accepted connections should look like ?
No, this is correct -- the callback you specify in a Begin... operation will always be called, even if you close the socket (if you close the socket, it will be called because of that). You should be catching the ObjectDisposedException you get on the EndAccept and then return without further action. Closing/disposing a socket/listener is the only way to cancel an asynchronous operation on it. (EndAccept can also produce SocketException, which should be handled normally.)
Using a flag you maintain yourself to check if the listener is still available is asking for trouble, because you're introducing shared state that needs to be synchronized (volatile reads and the like). You can easily introduce race conditions that way. The listener already maintains such a flag for you internally, which it uses to throw ObjectDisposedException, so I'd just use that. It's true that under normal circumstances catching ObjectDisposedException is a possible sign of a coding error (since you're supposed to know when an object is disposed), but with asynchronous code it's pretty standard.

Invalid program exception in release build (.NET 4.6.1)

I have a program that deals with socket communication asynchronously. The exception I've been getting only occurs in release build (on build machines). The code that causes the problem is really simple routine to start listening for incoming socket connections:
public async Task Listen()
{
try
{
var endpoint = new IPEndPoint(IPAddress.Loopback, Port);
using (Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
{
Socket.Bind(endpoint);
Socket.Listen(Limit);
while (!Shutdown)
{
var socket = await Socket.AcceptAsync().ConfigureAwait(false);
// some code handling connection
var result = await Socket.ReceiveAsync(state).ConfigureAwait(false);
Received(result, state);
}
}
}
catch (ObjectDisposedException) {}
catch (Exception ex) when (ex is SocketException || ex is ApplicationException || ex is ThreadAbortException)
{
OnError?.Invoke(this, ex);
Dispose();
}
}
AcceptAsync and ReceiveAsync are extension methods that use TPL pattern with Task.Factory.FromAsync. The exact exception is following:
Exception Type: System.InvalidProgramException
Exception Message: Common Language Runtime detected an invalid program.
This seem to occur in:
System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Start
The exception is generated instantly when call is made to this method. Any ideas what might be wrong?
According to MSDN, this exception informs the user about invalid IL code. So something could be broken in the framework. I recommend you to try your luck at Connect.Microsoft. Also, if you're really interested and are looking for a quick fix you may want to inspect the IL code of the failing methods' chain.

After disposing async socket (.Net) callbacks still get called

I feel, that I am misunderstanding something about async sockets in .Net. The situation is as follows : I have 1 async socket client and 1 async socket server. They communicate without any visible problems, but when I close listener and disconnect clients, the "OnConnectRequest" which is bound to "BeginAccept" as a callback, still gets called at least once. The "BeginReceive", "OnConnectRequest", "Disconnect" and "Dispose" methods are :
public void BeginReceive()
{
_listener.Bind(_endpoint);
_listener.Listen(_maxConnections);
try
{
_listener.BeginAccept(new AsyncCallback(OnConnectRequest), _listener);
}
catch (SocketException se)
{
OnListeningError(this, new Exception("Server cannot accept connections due to network shutdown or some fatal failure", se));
}
}
protected void OnConnectRequest(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket client = listener.EndAccept(ar);
var remoteEndpoint = client.RemoteEndPoint;
IDuplexStateObject state = new DuplexStateObject();
state.WorkSocket = client;
if (_clients.Count <= _maxConnections)
{
lock (_clients)
{
_clients.Add(state);
}
OnConnected(this, state);
}
else
{
//denying connection
client.Close();
AcceptingError(this, null, new Exception(string.Format("Maximal connection count reached, connection attempt {0} has been denied", (remoteEndpoint != null) ? remoteEndpoint.ToString() : null)));
}
//accept connections from other clients
try
{
listener.BeginAccept(new AsyncCallback(OnConnectRequest), listener);
}
catch (SocketException se)
{
if (se.SocketErrorCode == SocketError.TooManyOpenSockets)
{
OnListeningError(this, new Exception("Maximal connection count reached, not possible to create any more connections"));
}
else
{
OnListeningError(this, new Exception("Server cannot accept connections due to network shutdown or some fatal failure"));
}
}
}
public void Disconnect(IStateObject state)
{
if (state.WorkSocket == null)
{
//OnDisconnectError(this, state.ClientInfo,
// new Exception("No underlying work socket found for client. Already disconnected, disposing connection..."));
OnDisconnected(this, state.ClientInfo);
return;
}
try
{
if (state.WorkSocket.Connected)
{
state.WorkSocket.Shutdown(SocketShutdown.Both);
}
state.WorkSocket.Close();
}
catch (SocketException se)
{
OnDisconnectError(this, state.ClientInfo, se);
}
OnDisconnected(this, state.ClientInfo);
lock (_clients)
{
_clients.Remove(state);
}
}
public void Dispose()
{
_listener.Close();
//keys are cloned before disconnecting
foreach (var client in _clients.ToList())
{
Disconnect(client);
}
}
What I am doing is calling "Dispose" to closes listener and shut down all client sockets. The client is then still active, and it tries to reconnect, but what I expected to happen was server being completely unavailable on corresponding IP and port. What I see instead is "OnConnectRequest" callback being called, which crashes because of attempt to use already disposed socket. Can you please explain, what is wrong here, and how graceful shutdown of a listener and all accepted connections should look like ?
No, this is correct -- the callback you specify in a Begin... operation will always be called, even if you close the socket (if you close the socket, it will be called because of that). You should be catching the ObjectDisposedException you get on the EndAccept and then return without further action. Closing/disposing a socket/listener is the only way to cancel an asynchronous operation on it. (EndAccept can also produce SocketException, which should be handled normally.)
Using a flag you maintain yourself to check if the listener is still available is asking for trouble, because you're introducing shared state that needs to be synchronized (volatile reads and the like). You can easily introduce race conditions that way. The listener already maintains such a flag for you internally, which it uses to throw ObjectDisposedException, so I'd just use that. It's true that under normal circumstances catching ObjectDisposedException is a possible sign of a coding error (since you're supposed to know when an object is disposed), but with asynchronous code it's pretty standard.

Socket's state changes from Connected to Disconnected

I have two applications, one connects to another via TCP Socket. I was having an issue and after a long troubleshooting I begun to think the root cause is due to the disconnection of the Socket, aka the Socket.state changes to Disconnected.
The reasons I came to above conclusion are just purely from reading the codes and analyze them. I need to prove that is the case and therefore my question is have you ever came accross this type of issue that the socket actually keep getting disconnected even after trying to connect to them?
Below is my Connect code, I have a loop that constantly check for the socket's state itself, if I detect the state is "Disconnected" I call this Connect() function again. Upon each and every time I call Connect() I noticed my socket state is back to Connected again.
So my questions are:
1. Have you seen this behavior yourself before?
2. Do you see any problem in me calling multiple Connect() again and again?
3. Is there a way to simulate this type of socket disconnections? I tried but I can't set the Socket.Connected flag.
public override void Connect()
{
try
{
sState = Defs.STATE_CONNECTING;
// send message to UI
string sMsg = "<Msg SocketStatus=\"" + sState + "\" />";
HandleMessage(sMsg);
// Create the socket object
sSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
string sIP = "";
// Define the Server address and port
if (Validate.IsIPAddress(sServer.ToString()))
{
sIP = sServer.ToString();
}
else
{
IPHostEntry iphost = Dns.GetHostEntry(sServer.ToString());
sIP = iphost.AddressList[0].ToString();
}
IPEndPoint epServer = new IPEndPoint(IPAddress.Parse(sIP), 1234);
// Connect to Server non-Blocking method
sSock.Blocking = false;
AsyncCallback onconnect = new AsyncCallback(OnConnect);
sSock.BeginConnect(epServer, onconnect, sSock);
}
catch (Exception ex)
{
LogException(new Object[] { ex });
}
}

Async client handle receive?

I was told several times that async is better or that I should use async instead of sync sockets and as such started learning it, but am already having difficult.
I've got the basic feel of how the callback works and how to establish a connection.
I am using this msdn code as reference!
A few problems I am having with the code:
Currently that code will connect to the server, send a text, read the response and exit. How do I do so I can keep receiving the data until either the server disconnects me and/or I end it by myself ? I am not much sure on how I should do it, if I would need to wrap it on a thread with while or simple call that Receive again once the ReceiveCallback is done.
Another things I've noticed is when it connects, the socket is assigned to client but the code itself is always reassigning the client socket which I don't understand very well compared to the sync socket we have a main socket that we are always consulting etc.
I am not sure on how old the reference I am using is but would appreciate if you could help me with examples of what I have pointed out as it is easier for me to understand.
UPDATE:
private void SetupRecieveCallback(Socket sock)
{
new Thread(
delegate()
{
while (isReceiving)
{
_receiveQueue.Reset();
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
}
catch (Exception ex)
{
_logger.Error("Setup Recieve Callback failed! " + ex.Message);
}
_receiveQueue.WaitOne();
}
}
).Start();
/*
// The original code
try
{
AsyncCallback recieveData = new AsyncCallback(OnRecievedData);
sock.BeginReceive(m_byBuff, 0, m_byBuff.Length, SocketFlags.None, recieveData, sock);
}
catch (Exception ex)
{
_logger.Error("Setup Recieve Callback failed! " + ex.Message);
}
*/
}
Simply call BeginReceive() again in the callback to keep receiving. When the server breaks the connection then your callback will be called and EndReceive() throws an ObjectDisposedException. That's how you know to stop calling BeginReceive().
Second question is harder to decode (ask only one). I'm guessing you are puzzled about this statement:
private static void ConnectCallback(IAsyncResult ar) {
try {
// Retrieve the socket from the state object.
Socket client = (Socket) ar.AsyncState;
// etc..
No reassigning the socket is happening here. The code simply retrieves a reference to the original socket. Which is a useful technique, it allows this callback to be used by more than one connection. The ar.AsyncState value got to be the socket by this statement:
client.BeginConnect( remoteEP,
new AsyncCallback(ConnectCallback), client);
Note how client is passed to the AsyncCallback constructor. The exact same client that's retrieved in the callback. Any object can be passed.

Categories

Resources