Estoy recibiendo una excepción:

"An unhandled exception of type 'System.NotSupportedException' occurred in 
 System.dll

 Additional information: This protocol version is not supported."

Cuando ejecuto el siguiente código. Estoy tratando de implementar una conexión tcp asincrónica con un tiempo de espera.

He visto y leído varios ejemplos de desbordamiento de pila, algunos usando TcpClient y otros usando Socket. Supongo que el primero concluye con el segundo y es más nuevo. Estoy intentando con TcpClient.BeginConnect

La documentación no enumera NotSupported como uno de los tipos de excepción que este método puede generar. ¿Cómo puedo localizar cuál es el problema?

public class Client
{
    private string m_host;
    private uint m_port;
    private uint m_timeoutMilliseconds;
    private TcpClient m_client;

    public Client(string host, uint port, uint timeoutMilliseconds)
    {
        m_host = host;
        m_port = port;
        m_timeoutMilliseconds = timeoutMilliseconds;
        m_client = new TcpClient();
    }

    public bool Connect()
    {
        IPHostEntry hostInfo = Dns.GetHostEntry(m_host);
        IPAddress ipAddress = hostInfo.AddressList[0];
        IPEndPoint endpoint = new IPEndPoint(ipAddress, (int)m_port);

        IAsyncResult result = m_client.BeginConnect(ipAddress, (int)m_port, new AsyncCallback(OnConnect), m_client);
        result.AsyncWaitHandle.WaitOne((int)m_timeoutMilliseconds, true);

        // SNIP

        return true;
    }

    public void Disconnect()
    {
        throw new NotImplementedException();
    }

    public void MakeRequest(string symbol)
    {
        throw new NotImplementedException();
    }


    private static void OnConnect(IAsyncResult asyncResult)
    {
        Socket socket = (Socket)asyncResult.AsyncState;
        socket.EndConnect(asyncResult);

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

    }
}

class Program
{
    static void Main(string[] args)
    {
        Client client = new Integration.Client("127.0.0.1", 24001, 360000);
        client.Connect();
    }
}
0
Christopher Pisz 13 nov. 2017 a las 23:12

2 respuestas

La mejor respuesta

De forma predeterminada, TcpClient asume que estás usando una dirección IPv4. Hay una sobrecarga de constructor que le permite Sin embargo, especifique qué familia de direcciones usar, pero esto significaría construirla después de haber realizado la búsqueda de dns:

m_client = new TcpClient(ipAddress.AddressFamily);
IAsyncResult result = m_client.BeginConnect(ipAddress, (int)m_port, new AsyncCallback(OnConnect), m_client);

Alternativamente, puede encontrar la dirección IPv4 en hostInfo.AddressList y conectarse a ella; eso es lo que BeginConnect(string host, ...) la sobrecarga lo hace bajo el capó (a menos que haya especificado IPv6 en el constructor).

No tengo idea de por qué no tomaron el AddressFamily del IPAddress que estás pasando, quizás porque el Socket subyacente se crea en el constructor TcpClient. También me sorprendió ver lo siguiente en la referencia página de origen de TcpClient:

//
// IPv6: Maintain address family for the client
//
AddressFamily m_Family = AddressFamily.InterNetwork;

No entiendo ese comentario, pero aparentemente alguien tenía en mente IPv6 al elegir el predeterminado.

1
C.Evenhuis 13 nov. 2017 a las 21:01

Si solo busca una dirección local IP4, intente esto

using System.Linq;

IPAddress ipAddress = Dns.GetHostEntry(m_host).AddressList.FirstOrDefault(x => x.IsIPv6LinkLocal == false);

Acabo de probar su ejemplo y tuve el mismo error, con lo anterior parecía funcionar.

0
jack_tux 13 nov. 2017 a las 21:10