[英]How to control the connect timeout with the Winsock API?
我正在使用Winsock API编写程序,因为一个朋友想要一个简单的程序来检查Minecraft服务器是否正在运行。 如果它正在运行,它可以正常工作,但是,如果它不在运行,则程序将冻结直到我假设连接超时。 另一个问题是,如果我有类似以下内容(伪代码):
void connectButtonClicked()
{
setLabel1Text("Connecting");
attemptConnection();
setLabel1Text("Done Connecting!");
}
它似乎跳过了tryConnection()的权限,完全忽略了它上面的内容。 我注意到这是因为程序将冻结,但不会将标签更改为“正在连接”。
这是我的实际连接代码:
bool CConnectionManager::ConnectToIp(String^ ipaddr)
{
if(!m_bValid)
return false;
const char* ip = StringToPConstChar(ipaddr);
m_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(isalpha(ip[0]))
{
ip = getIPFromAddress(ipaddr);
}
sockaddr_in service;
service.sin_family = AF_INET;
service.sin_addr.s_addr = inet_addr(ip);
service.sin_port = htons(MINECRAFT_PORT);
if(m_socket == NULL)
{
return false;
}
if (connect(m_socket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR)
{
closesocket(m_socket);
return false;
}
else
{
closesocket(m_socket);
return true;
}
return true;
}
CConnectionManager的构造器中也有代码可以启动Winsock API等。
因此,如何避免这种冻结,并允许我在连接期间更新进度条之类的内容? 我是否必须在单独的线程中进行连接? 我只使用Java中的线程,所以我不知道该怎么做:/
另外:我正在使用CLR Windows窗体应用程序
我正在使用Microsoft Visual C ++ 2008 Express Edition
您的代码不会跳过标签更新。 该更新仅涉及发出尚未处理的窗口消息,这就是为什么在连接套接字之前看不到新文本出现的原因。 在连接套接字之前,您将必须为新消息泵送消息队列。
至于套接字本身,不幸的是,WinSock API中没有连接超时。 您有两种选择来实现手动超时:
1)假设您正在使用阻塞套接字(默认情况下套接字处于阻塞状态),请在单独的工作线程中执行连接。
2)如果您不想使用线程,则将套接字切换为非阻塞模式。 连接套接字总是会立即退出,因此您的主代码不会被阻止,然后您会在以后收到连接成功的通知。 有几种方法可以检测到这种情况,具体取决于您使用的API-WSAAsyncSelect(),WSAAsyncEvent()或select()。
无论哪种方式,在进行连接时,都要在主线程中运行一个计时器。 如果连接成功,请停止计时器。 如果计时器过去,请断开套接字,这将导致连接异常中止。
也许您想在这里阅读:
为了确保所有数据在关闭之前在连接的套接字上发送和接收,应用程序应在调用closesocket之前使用shutdown关闭连接。 http://msdn.microsoft.com/en-us/library/ms740481%28v=VS.85%29.aspx
由于您处于阻止模式,因此仍然可能会有一些数据...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.