Reputation: 4010
I am getting an exception:
"An unhandled exception of type 'System.NotSupportedException' occurred in
System.dll
Additional information: This protocol version is not supported."
when I run the following code. I am trying to implement an asynchronous tcp connection with a timeout.
I've seen and read several stack overflow examples, some using TcpClient and some using Socket. I assume the former wraps up the latter and is newer. I am trying with TcpClient.BeginConnect
The documentation does not list NotSupported as one of the exception types this method can throw. How do I track down what the problem is?
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();
}
}
Upvotes: 0
Views: 421
Reputation: 429
If you are only after an IP4 local address try this
using System.Linq;
IPAddress ipAddress = Dns.GetHostEntry(m_host).AddressList.FirstOrDefault(x => x.IsIPv6LinkLocal == false);
I just tried your example and had the same error, with the above it seemed to work.
Upvotes: 0
Reputation: 26446
By default, TcpClient
assumes you're using an IPv4 address. There's a constructor overload that lets you specify which address family to use though, but this would mean constructing it after you've done the dns lookup:
m_client = new TcpClient(ipAddress.AddressFamily);
IAsyncResult result = m_client.BeginConnect(ipAddress, (int)m_port, new AsyncCallback(OnConnect), m_client);
Alternatively you could find the IPv4 address in the hostInfo.AddressList
and connect to that - that's what the BeginConnect(string host, ...)
overload does for you under the hood (unless you have specified IPv6 in the constructor).
I have no idea why they didn't just take the AddressFamily
from the IPAddress
you're passing, perhaps because the underlying Socket
is created in the TcpClient
constructor. I was also suprised to see the following in the reference source page of TcpClient
:
//
// IPv6: Maintain address family for the client
//
AddressFamily m_Family = AddressFamily.InterNetwork;
I don't understand that comment, but apparently someone did have IPv6 in mind when choosing the default.
Upvotes: 1