Receiving SocketException (0x80004005) when logging into VPN

Viewed 1060

I have been troubleshooting an issue that I encountered when using a library called AMQP .Net Lite (https://github.com/Azure/amqpnetlite) and have determined that it can be reproduced using a simple .NET Sockets client and server. My repro environment uses a client that sends simple text messages to the server based on some Microsoft samples (see below).

I have noticed after I sign into my company VPN that messages fail to transfer with the following error:

SocketException : System.Net.Sockets.SocketException (0x80004005): An existing connection was forcibly closed by the remote host

I am running both client and server locally on my machine when I encounter the issue.

I have read about this exception and learned that one cause is that the network link has gone down for some reason. This makes sense as logging into VPN must temporarily break the connection, thereby causing the exception. However, one interesting observation is that this problem only occurs when the server is hosting using IPv6. If I force it to use IPv4, then there is no loss of connectivity. Is there a simple explanation for that?

I am also wondering if there is some way to detect that the Socket is in a bad state without sending data? Are there some properties on the Socket I can inspect such that I can detect an issue and force a reconnect? If not, what do people typically do in this situation to ensure the failed messages are accounted for after reconnection?

Interestingly, with my test client, I have to send 2 messages before the exception is thrown, but neither message is received by the server (see picture below).

I am not a networking expert so bear with me if this is fundamental stuff.

Here is my client:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

public class SynchronousSocketClient
{

    public static void StartClient()
    {
        // Data buffer for incoming data.  
        byte[] bytes = new byte[1024];

        // Connect to a remote device.  
        try
        {
            // Establish the remote endpoint for the socket.  
            // This example uses port 11000 on the local computer.  
            IPHostEntry ipHostInfo = Dns.GetHostEntry(Environment.MachineName);
            IPAddress ipAddress = ipHostInfo.AddressList[0];
            IPEndPoint remoteEP = new IPEndPoint(ipAddress, 11000);

            // Create a TCP/IP  socket.  
            Socket sender = new Socket(AddressFamily.InterNetworkV6,
                SocketType.Stream, ProtocolType.Tcp);

            // Connect the socket to the remote endpoint. Catch any errors.  
            try
            {
                sender.Connect(remoteEP);

                Console.WriteLine("Socket connected to {0}",
                    sender.RemoteEndPoint.ToString());

                // Encode the data string into a byte array.  
                byte[] msg = Encoding.ASCII.GetBytes("This is a test");

                Console.WriteLine("Press any key to send a message...");
                int i = 0;

                while (true)
                {
                    Console.ReadLine();
                    // Send the data through the socket.  
                    int bytesSent = sender.Send(msg);
                    Console.WriteLine(++i + " messages sent");
                }

                // Receive the response from the remote device.  
                int bytesRec = sender.Receive(bytes);
                Console.WriteLine("Echoed test = {0}",
                    Encoding.ASCII.GetString(bytes, 0, bytesRec));

                // Release the socket.  
                sender.Shutdown(SocketShutdown.Both);
                sender.Close();

            }
            catch (ArgumentNullException ane)
            {
                Console.WriteLine("ArgumentNullException : {0}", ane.ToString());
            }
            catch (SocketException se)
            {
                Console.WriteLine("SocketException : {0}", se.ToString());
            }
            catch (Exception e)
            {
                Console.WriteLine("Unexpected exception : {0}", e.ToString());
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.ReadLine();
    }

    public static int Main(String[] args)
    {
        StartClient();
        return 0;
    }
}

Here is my server:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;

public class SynchronousSocketListener
{

    // Incoming data from the client.  
    public static string data = null;

    public static void StartListening()
    {
        // Data buffer for incoming data.  
        byte[] bytes = new Byte[1024];

        // Establish the local endpoint for the socket.  
        // Dns.GetHostName returns the name of the   
        // host running the application.  
        IPEndPoint localEndPoint = new IPEndPoint(IPAddress.IPv6Any, 11000);

        // Create a TCP/IP socket.  
        Socket listener = new Socket(AddressFamily.InterNetworkV6,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and   
        // listen for incoming connections.  
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(10);

            // Start listening for connections.  
            while (true)
            {
                Console.WriteLine("Waiting for a connection...");
                // Program is suspended while waiting for an incoming connection.  
                Socket handler = listener.Accept();

                // An incoming connection needs to be processed.  
                while (true)
                {
                    bytes = new byte[1024];
                    int bytesRec = handler.Receive(bytes);
                    data = Encoding.ASCII.GetString(bytes, 0, bytesRec);
                    Console.WriteLine(data);
                }

                // Show the data on the console.  
                Console.WriteLine("Text received : {0}", data);

                // Echo the data back to the client.  
                byte[] msg = Encoding.ASCII.GetBytes(data);

                handler.Send(msg);
                handler.Shutdown(SocketShutdown.Both);
                handler.Close();
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

        Console.WriteLine("\nPress ENTER to continue...");
        Console.Read();

    }

    public static int Main(String[] args)
    {
        StartListening();
        return 0;
    }
}

Here is a screenshot of the problem:

SocketException

0 Answers
Related