我选择不使用异步调用,因为它需要回调,我只是好奇是否有办法通过利用类似Unix的非阻塞套接字来解决这个问题方法:Poll(),因为Asyn是专门为Windows环境创建的。我正在研究是否可以在没有异步的情况下完成。
需要注意的是:非阻塞!=异步:)
因此我通过关闭socket& amp;阻塞标志来实现以下方法: Poll()方法:
try
{
IPEndPoint hostEp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11000);
Socket hostSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
hostSock.Blocking = false;
hostSock.Connect(hostEp);
}
catch (Win32Exception se)
{
if (ex.ErrorCode == 10035) // WSAEWOULDBLOCK is expected, means connect is in progress
while (true)
{
Console.WriteLine("Connecting in progress");
bool connected = hostSock.Poll(1000000, SelectMode.SelectWrite);
if (connected)
{
Console.WriteLine("Connected");
break;
}
}
}
但是SelectMode.SelectWrite似乎并没有为我重新启动连接尝试。那么,问题是什么?我怎么能解决这个问题?我应该使用Select() instead of Poll()?
吗?答案 0 :(得分:4)
只需使用异步方法(ConnectAsync()
),它们就是为此而设的。不要对程序逻辑使用异常。
您可以同步Connect()
TCP套接字而不会阻塞:
除非在调用Connect之前将Blocking属性专门设置为false,否则Connect方法将被阻止。如果您正在使用面向连接的协议(如TCP)并且禁用阻止,则Connect将抛出SocketException,因为它需要时间来建立连接。
您可以使用SocketException.ErrorCode获取特定的错误代码。获取此代码后,请参阅MSDN库中的Windows套接字版本2 API错误代码文档,以获取错误的详细说明。
如果错误返回WSAEWOULDBLOCK,则远程主机连接已由面向连接的Socket启动,但尚未成功完成。使用Poll方法确定Socket何时完成连接。
但这正是你的代码所做的,所以这应该可行。
答案 1 :(得分:1)
您可以使用threads或tasks启动Connect,而不会阻止主线程。
如果由于跨线程保护而需要与UI(WinForms / WPF)进行交互,这将增加复杂性。
此外,您可以使用BackgroundWorker来避免此问题。
答案 2 :(得分:1)
实际上,您的代码正在我的系统上运行。但是,您当然需要一个接受TCP连接的服务器。如果你没有,那么你将永远等待。所以我猜你错过了一台服务器。
答案 3 :(得分:1)
我有一个确切的问题,但是对我来说答案很愚蠢:我的代码具有用于从字符串(从microsoft)中获取IpAddress的股票代码:
var ipHostInfo = Dns.GetHostEntry(hostname);
return ipHostInfo.AddressList[0];
这一切都很好,但是我的测试是针对“ 127.0.0.1:9000”进行的,由于某种原因,该网关控制了我实际的以太网连接的IP地址。将解析机制更改为:
if (hostname.Equals("localhost"))
{
return IPAddress.Parse("127.0.0.1");
}
try
{
return IPAddress.Parse(hostname);
}
catch (FormatException e)
{
var ipHostInfo = Dns.GetHostEntry(hostname);
return ipHostInfo.AddressList[0];
}
成功了(至少对我来说是这样!)