System.Net.Sockets.SocketException

The exception that is thrown when a socket error occurs.

Minimum version: >= 1.1 >= Core 1.0

Statistics

9
elmah.io logo 10

How to handle it

try
{

}
catch (System.Net.Sockets.SocketException e)
{

}
try
{

}
catch (System.Net.Sockets.SocketException e) when (e.Message.Contains("something"))
{

}
try
{

}
catch (System.Net.Sockets.SocketException e) when (LogException(e))
{

}

private static bool LogException(Exception e)
{
    logger.LogError(...);
    return false;
}

How to avoid it

We haven't written anything about avoiding this exception yet. Got a good tip on how to avoid throwing System.Net.Sockets.SocketException? Feel free to reach out through the support widget in the lower right corner with your suggestions.

Links

YouTube videos

Possible fixes from StackOverflow

As you may be aware, if a host receives a packet for a UDP port that is not currently bound, it may send back an ICMP "Port Unreachable" message. Whether or not it does this is dependent on the firewall, private/public settings, etc. On localhost, however, it will pretty much always send this packet back.

In your server code, you are calling SendAsync to old clients, which prompts these "port unreachable" messages.

Now, on Windows (and only on Windows), by default, a received ICMP Port Unreachable message will close the UDP socket that sent it; hence, the next time you try to receive on the socket, it will throw an exception because the socket has been closed by the OS.

Obviously, this causes a headache in the multi-client, single-server socket set-up you have here, but luckily there is a fix:

You need to utilise the not-often-required SIO_UDP_CONNRESET Winsock control code, which turns off this built-in behaviour of automatically closing the socket.

I don't believe this ioctl code is available in the dotnet IoControlCodes type, but you can define it yourself. If you put the following code at the top of your server repro, the error no longer gets raised.

const uint IOC_IN = 0x80000000U;
const uint IOC_VENDOR = 0x18000000U;

/// <summary>
/// Controls whether UDP PORT_UNREACHABLE messages are reported. 
/// </summary>
const int SIO_UDP_CONNRESET = unchecked((int)(IOC_IN | IOC_VENDOR | 12));

var udpClient = new UdpClient(9001);
udpClient.Client.IOControl(SIO_UDP_CONNRESET, new byte[] { 0x00 }, null);

Note that this ioctl code is only supported on Windows (XP and later), not on Linux, since it is provided by the Winsock extensions. Of course, since the described behavior is only the default behavior on Windows, this omission is not a major loss. If you are attempting to create a cross-platform library, you should cordon this off as Windows-specific code.

On Windows Vista (and Windows 7), Dns.GetHostEntry also returns IPv6 addresses. In your case, the IPv6 address (::1) is first in the list.

You cannot connect to an IPv6 (InterNetworkV6) address with an IPv4 (InterNetwork) socket.

Change your code to create the socket to use the address family of the specified IP address:

Socket serverSocket =
    new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                        ↑

Note: There's a shortcut to obtain the IP address of localhost: You can simply use IPAddress.Loopback (127.0.0.1) or IPAddress.IPv6Loopback (::1).

An established connection was aborted by the software in your host machine

That is a boiler-plate error message, it comes out of Windows. The underlying error code is WSAECONNABORTED. Which really doesn't mean more than "connection was aborted". You have to be a bit careful about the "your host machine" part of the phrase. In the vast majority of Windows application programs, it is indeed the host that the desktop app is connected to that aborted the connection. Usually a server somewhere else.

The roles are reversed however when you implement your own server. Now you need to read the error message as "aborted by the application at the other end of the wire". Which is of course not uncommon when you implement a server, client programs that use your server are not unlikely to abort a connection for whatever reason. It can mean that a fire-wall or a proxy terminated the connection but that's not very likely since they typically would not allow the connection to be established in the first place.

You don't really know why a connection was aborted unless you have insight what is going on at the other end of the wire. That's of course hard to come by. If your server is reachable through the Internet then don't discount the possibility that you are being probed by a port scanner. Or your customers, looking for a game cheat.

Is it possible that the serverSocket is being closed from another thread? That will cause this exception.

You just need to keep digging. The exception "The response ended prematurely" isn't the root cause. Keep digging into the inner exceptions until you find the last one. You'll find this:

System.IO.IOException: Authentication failed because the remote party has closed the transport stream.

So it's not about your code. It seems the server you're hitting either can't handle the load, or is intentionally dropping your requests because you're hitting it too hard.