>我得到一个异常:
"An unhandled exception of type 'System.NotSupportedException' occurred in
System.dll
Additional information: This protocol version is not supported."
当我运行以下代码时。我正在尝试实现超时的异步 tcp 连接。
我已经看到并阅读了几个堆栈溢出示例,一些使用TcpClient,一些使用Socket。我认为前者包抄了后者,并且是较新的。我正在尝试使用TcpClient.BeginConnect
文档未将 NotSupport 列为此方法可能引发的异常类型之一。如何追踪问题所在?
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();
}
}
默认情况下,TcpClient
假定您使用的是 IPv4 地址。有一个构造函数重载,允许您指定要使用的地址系列,但这意味着在完成 dns 查找后构造它:
m_client = new TcpClient(ipAddress.AddressFamily);
IAsyncResult result = m_client.BeginConnect(ipAddress, (int)m_port, new AsyncCallback(OnConnect), m_client);
或者,您可以在hostInfo.AddressList
中找到 IPv4 地址并连接到该地址 - 这就是BeginConnect(string host, ...)
重载在后台为您所做的(除非您在构造函数中指定了 IPv6(。
我不知道为什么他们不只是从您传递的IPAddress
中获取AddressFamily
,也许是因为底层Socket
是在TcpClient
构造函数中创建的。我也惊讶地在TcpClient
的参考源页面中看到以下内容:
//
// IPv6: Maintain address family for the client
//
AddressFamily m_Family = AddressFamily.InterNetwork;
我不明白这个评论,但显然有人在选择默认值时确实考虑了IPv6。
如果您只在IP4本地地址之后尝试此操作
using System.Linq;
IPAddress ipAddress = Dns.GetHostEntry(m_host).AddressList.FirstOrDefault(x => x.IsIPv6LinkLocal == false);
我刚刚尝试了您的示例并遇到了相同的错误,上面似乎有效。