C#: Error on Shutdown of Socket? - c#

I am trying to dispose of a console application, one part of disposing this is shutting down the server socket, but when I try I get a SocketException and I'm unsure why?
System.Net.Sockets.SocketException: 'A request to send or receive data
was disallowed because the socket is not connected and (when sending
on a datagram socket using a sendto call) no address was supplied'
I dispose of the class here, by calling Socket.Shutdown, which is where the error gets thrown.
public void Dispose()
{
if (_serverSocket == null)
{
return;
}
_serverSocket.Shutdown(SocketShutdown.Both);
_serverSocket.Close();
_serverSocket.Dispose();
}

Because
_serverSocket.Shutdown(SocketShutdown.Both);
_serverSocket.Close();
already drop connection, so that you don't need _serverSocket.Dispose(); anymore

Related

UdpClient not failing when endpoint is unavailable

It was my expectation that, if the endpoint is not available, the UdpClient.Connect() method would throw an exception that I could capture and, say, alter a label's text to say if the program was connected to the server or not. However, despite me having turned off the server that I'm trying to connect to, the method completes with no issue. Is there some way to resolve this issue, or some other method I should be attempting?
My current code (IP address blanked out, but is valid):
UdpClient chatConnection = new UdpClient();
IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("xxx.xx.xxx.xxx"), 1000);
// Initialize client/server connection and set status text
try
{
chatConnection.Connect(serverEndPoint);
SL_Status.Text = "Connected";
}
catch (Exception ex)
{
SL_Status.Text = "Not Connected";
MessageBox.Show("Unable to connect to server. See console for logs.");
Console.WriteLine(ex);
}
Since UDP is connectionless checking if client is connected doesn't apply to it.
There is however a workaround that in some cases may work:
answer by Yahia

Mono obtain remote ip address when socket is timed out

catch (SocketException se)
{
if(se.ErrorCode == 10054 || se.ErrorCode == 10053) // Error code for Connection reset by peer
{
Console.WriteLine("User from " + currentSocket.RemoteEndPoint.ToString() + " timed out");
}
}
I have a problem with socket exception with mono, above code runs perfectly on windows, while on mono throws exception that RemoteEndPoint is null.
My question is how to obtain ip address of disconnected user using mono?
Create a wrapper which holds the socket and any additional information you need. Upon connection, you can populate the values you want to save such as their ip address. When a disconnect occurs, you can log from this variable instead of off the socket object.

Application crash without throwing exception if Socket.BeginSend is called after the socket is closed

I'm writing a socket application that asynchronously polls several servers at once and reports any changes in their states to the user. So far everything is working, except for one small bug I can't seem to figure out.
The server creates a bunch of sockets every 10 seconds, then calls an async connect. This is then handled by a ProcessConnectionComplete(IAsyncResult iar) method, which then calls both Socket.BeginReceive and then Socket.Begin send. Any received data is then handled with another method.
Then, at the end of the 10 seconds before the next wave of sockets is created, any sockets that have not already received data and closed are forcefully closed by a loop.
The issue I am having is that if the socket happens to close just before the Socket.BeginSend method is called (ie someone trips over a network cable, or the server on the other end crashes), the program exits without exeption (error code 0), when it should throw an exception. Here's the code:
private static void ProcessConnectionComplete(IAsyncResult iar)
{
SocketState state = iar.AsyncState as SocketState;
if (state.Socket.Connected)
{
// start waiting for a reply
state.Socket.BeginReceive(state.Buffer, 0, state.Buffer.Length, SocketFlags.None, new AsyncCallback(frm_Server_Poll.ProcessAsyncReceive), state);
//state.Socket.Close(); // if socket is closed after .Connected check and before BeginSend, crash occurs
try
{
// send message
state.Socket.BeginSend(new byte[] { (byte)'\xfe' }, 0, 1, SocketFlags.None, null, state);
}
catch (Exception ex) // Never called, EXCEPTION WHERE ARE YOU???
{
throw (ex);
}
}
else
{
state.ServerInfo.connected = false;
}
}
Why is this happening? I have some idea that it is to do with the way threading is handled with Async calls, but have no idea how to catch the exception. Any help would be greatly appreciated.
The exception should occur in the callback (frm_Server_Poll.ProcessAsyncReceive) when calling Socket.EndReceive.
Likewise, for the send, the exception should occur in its callback when calling Socket.EndSend. However, your BeginSend does not have a callback with which to handle errors.
I cannot be certain, but I suspect that this is why the exception is getting mysteriously lost.
It's worth noting that both BeginReceive and BeginSend can throw directly if the socket is disposed at the time they are called.
if the socket happens to close just before the Socket.BeginSend method
is called (ie someone trips over a network cable, or the server on the
other end crashes)
I do not understand. Neither of those events will close your socket. Only you can close your socket. Those events can abort the connection, in which case your send will get whatever exception an ECONNRESET maps to in C#. If you close the socket yourself and then send, you will get whatever EBADF maps to if nothing else in C# traps it first.

The I/O operation has been aborted because of either a thread exit or an application request

My application is working as a client application for a bank server. The application is sending a request and getting a response from the bank. This application is normally working fine, but sometimes
The I/O operation has been aborted because of either a thread exit or
an application request
error with error code as 995 comes through.
public void OnDataReceived(IAsyncResult asyn)
{
BLCommonFunctions.WriteLogger(0, "In :- OnDataReceived",
ref swReceivedLogWriter, strLogPath, 0);
try
{
SocketPacket theSockId = (SocketPacket)asyn.AsyncState;
int iRx = theSockId.thisSocket.EndReceive(asyn); //Here error is coming
string strHEX = BLCommonFunctions.ByteArrToHex(theSockId.dataBuffer);
}
}
Once this error starts to come for all transactions after that same error begin to appear, so
please help me to sort out this problem. If possible then with some sample code
Regards,
Ashish Khandelwal
995 is an error reported by the IO Completion Port. The error comes since you try to continue read from the socket when it has most likely been closed.
Receiving 0 bytes from EndRecieve means that the socket has been closed, as does most exceptions that EndRecieve will throw.
You need to start dealing with those situations.
Never ever ignore exceptions, they are thrown for a reason.
Update
There is nothing that says that the server does anything wrong. A connection can be lost for a lot of reasons such as idle connection being closed by a switch/router/firewall, shaky network, bad cables etc.
What I'm saying is that you MUST handle disconnections. The proper way of doing so is to dispose the socket and try to connect a new one at certain intervals.
As for the receive callback a more proper way of handling it is something like this (semi pseudo code):
public void OnDataReceived(IAsyncResult asyn)
{
BLCommonFunctions.WriteLogger(0, "In :- OnDataReceived", ref swReceivedLogWriter, strLogPath, 0);
try
{
SocketPacket client = (SocketPacket)asyn.AsyncState;
int bytesReceived = client.thisSocket.EndReceive(asyn); //Here error is coming
if (bytesReceived == 0)
{
HandleDisconnect(client);
return;
}
}
catch (Exception err)
{
HandleDisconnect(client);
}
try
{
string strHEX = BLCommonFunctions.ByteArrToHex(theSockId.dataBuffer);
//do your handling here
}
catch (Exception err)
{
// Your logic threw an exception. handle it accordinhly
}
try
{
client.thisSocket.BeginRecieve(.. all parameters ..);
}
catch (Exception err)
{
HandleDisconnect(client);
}
}
the reason to why I'm using three catch blocks is simply because the logic for the middle one is different from the other two. Exceptions from BeginReceive/EndReceive usually indicates socket disconnection while exceptions from your logic should not stop the socket receiving.
In my case, the request was getting timed out. So all you need to do is to increase the time out while creating the HttpClient.
HttpClient client = new HttpClient();
client.Timeout = TimeSpan.FromMinutes(5);
I had the same issue with RS232 communication. The reason, is that your program executes much faster than the comport (or slow serial communication).
To fix it, I had to check if the IAsyncResult.IsCompleted==true. If not completed, then IAsyncResult.AsyncWaitHandle.WaitOne()
Like this :
Stream s = this.GetStream();
IAsyncResult ar = s.BeginWrite(data, 0, data.Length, SendAsync, state);
if (!ar.IsCompleted)
ar.AsyncWaitHandle.WaitOne();
Most of the time, ar.IsCompleted will be true.
I had this problem. I think that it was caused by the socket getting opened and no data arriving within a short time after the open. I was reading from a serial to ethernet box called a Devicemaster. I changed the Devicemaster port setting from "connect always" to "connect on data" and the problem disappeared. I have great respect for Hans Passant but I do not agree that this is an error code that you can easily solve by scrutinizing code.
In my case the issue was caused by the fact that starting from .NET 5 or 6 you must either call async methods for async stream, or sync methods for sync strem.
So that if I called FlushAsync I must have get context using GetContextAsync
What I do when it happens is Disable the COM port into the Device Manager and Enable it again.
It stop the communications with another program or thread and become free for you.
I hope this works for you. Regards.
I ran into this error while using Entity Framework Core with Azure Sql Server running in Debug mode in Visual Studio. I figured out that it is an exception, but not a problem. EF is written to handle this exception gracefully and complete the work. I had VS set to break on all exceptions, so it did. Once I unchecked the check box in VS to not break on this exception, my C# code, calling EF, using Azure Sql worked every time.

IBM MQSeries Problem: remote host closes connection when writing message (error 10054)

I am trying to write to an IBM MQSeries host with:
public void WriteMessage(string message)
{
queueMessage = new MQMessage();
queueMessage.WriteString(message);
queueMessage.Format = MQC.MQFMT_STRING;
queuePutMessageOptions = new MQPutMessageOptions();
queue.Put(queueMessage, queuePutMessageOptions);
}
My errorcatch gives me an error however:
Error in the application
Which doesn't show much of course. So I checked the event log on the server and this showed me the error:
An error occurred receiving data from
stx041774 (192.168.225.51) over
TCP/IP. This may be due to a
communications failure.
The return code from the TCP/IP (recv) call was 10054 (X'2746').
Record these values and tell the
systems administrator.
I looked up 10054 and means:
An existing connection was forcibly
closed by the remote host.
Does anyone have any idea what I can do to make this work? Is there perhaps an MQC option I have to set for writing? Because I have no idea what to do with the options, I'm not even sure if this is the issue.
I solved this issue with an option mqc.mqoo_output:
queue = qManager.AccessQueue(QueueName, MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING);

Categories