[英]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.