開啟FTP測試線程:
1、線程聲明:
static DWORD WINAPI FtpCheckThread(LPVOID lpParam);
2、線程開啟:
CloseHandle(CreateThread( NULL,0,FtpCheckThread,this,0,NULL));
3、線程實現:
InternetOpen最後一個參數設定為非同步模型。
DWORD WINAPI CMainFrame::FtpCheckThread(LPVOID lpParam){CMainFrame* pThis = (CMainFrame*)lpParam;CString strIp,strPort,strUser,strPassword;BOOL bSuccess = FALSE;HINTERNET hInternet = NULL;HINTERNET hFtp = NULL;NETINFO* pNetInfo = new NETINFO;if (pNetInfo != NULL){pNetInfo->m_hEvent = CreateEvent(NULL,TRUE, //手動FALSE, //初始無訊號NULL);pNetInfo->m_bSuccess = FALSE;pNetInfo->m_hHandle = NULL;}pThis->m_DlgBar.GetDlgItemText(IDC_ED_IP,strIp);pThis->m_DlgBar.GetDlgItemText(IDC_ED_PORT,strPort);pThis->m_DlgBar.GetDlgItemText(IDC_ED_USER,strUser);pThis->m_DlgBar.GetDlgItemText(IDC_ED_PASSWORD,strPassword);while(TRUE){if(hInternet != NULL){InternetCloseHandle(hInternet);Sleep(200);hInternet = NULL;}hInternet = InternetOpen(NULL,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,INTERNET_FLAG_ASYNC);if (hInternet != NULL){InternetSetStatusCallback(hInternet,InternetStatusCallback);//設定回呼函數if(hFtp != NULL){InternetCloseHandle(hFtp);Sleep(500);hFtp = NULL;}TCHAR* pWideChar = strPort.GetBuffer(strPort.GetLength());char* pChar = WideCharToAnsi(pWideChar);strPort.ReleaseBuffer();hFtp = InternetConnect(hInternet,strIp,atoi(pChar),strUser,strPassword,INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE,(DWORD_PTR)pNetInfo);if (hFtp && GetLastError() != ERROR_IO_PENDING){//pThis->MessageBox(_T("第一次串連就成功了。"));gstrNetWorkMsg = _T("網路連接成功!");::PostMessage(pThis->m_hWnd,WM_NETSTATEMSG,0,0);}else{if (WaitForSingleObject(pNetInfo->m_hEvent,10000) == WAIT_OBJECT_0){ResetEvent(pNetInfo->m_hEvent);hFtp = pNetInfo->m_hHandle;pNetInfo->m_hHandle = NULL;}if (hFtp == NULL){//網路連接失敗,正嘗試重新串連gstrNetWorkMsg = _T("網路連接失敗,正嘗試重新串連...");::PostMessage(pThis->m_hWnd,WM_NETSTATEMSG,0,0);} else{//網路連接成功。。。gstrNetWorkMsg = _T("網路連接成功!");::PostMessage(pThis->m_hWnd,WM_NETSTATEMSG,0,0);Sleep(1000);bSuccess = FtpCommadCheck(hFtp,pNetInfo);if (bSuccess){//NetWork OkgstrNetWorkMsg = _T("NetWork Ok!");::PostMessage(pThis->m_hWnd,WM_NETSTATEMSG,0,0);} else{//NetWork ErrorgstrNetWorkMsg = _T("NetWork Error!");::PostMessage(pThis->m_hWnd,WM_NETSTATEMSG,0,0);}}Sleep(1000);}delete[] pChar;//......}else{Sleep(1000);}Sleep(10000);}return 1;}
其中:FtpCheckThread()函數中涉及到的幾個函數的實現如下:
1)回呼函數的聲明和實現:
void CALLBACK InternetStatusCallback(HINTERNET hInternet,DWORD_PTR dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation,DWORD dwStatusInformationLength);
void CALLBACK InternetStatusCallback(HINTERNET hInternet,DWORD_PTR dwContext,DWORD dwInternetStatus,LPVOID lpvStatusInformation,DWORD dwStatusInformationLength){if (dwInternetStatus == INTERNET_STATUS_REQUEST_COMPLETE){INTERNET_ASYNC_RESULT *Result = (INTERNET_ASYNC_RESULT*)lpvStatusInformation;if(Result->dwError == ERROR_SUCCESS){((NETINFO*)dwContext)->m_hHandle = (HINTERNET)Result->dwResult;((NETINFO*)dwContext)->m_bSuccess = (BOOL)Result->dwResult;SetEvent(((NETINFO*)dwContext)->m_hEvent);}}}
2)WideCharToAnsi的實現:
char *WideCharToAnsi(wchar_t *pWideChar) { if (!pWideChar) return NULL; char *pszBuf = NULL; int needBytes = WideCharToMultiByte(CP_ACP, 0, pWideChar, -1, NULL, 0, NULL, NULL); if (needBytes > 0){ pszBuf = new char[needBytes+1]; ZeroMemory(pszBuf, (needBytes+1)*sizeof(char)); WideCharToMultiByte(CP_ACP, 0, pWideChar, -1, pszBuf, needBytes, NULL, NULL); } return pszBuf; }
3)FtpCommadCheck函數的實現:
BOOL FtpCommadCheck(HINTERNET hFtp, NETINFO* pNetInfo)//測試FTP串連{CString sTmp;BOOL success = FALSE;success = FtpCommand(hFtp, FALSE, FTP_TRANSFER_TYPE_BINARY, _T("NOOP"), (DWORD)pNetInfo, NULL);if(!success){if ( WaitForSingleObject(pNetInfo->m_hEvent,1000) == WAIT_OBJECT_0 ){ResetEvent(pNetInfo->m_hEvent);success = pNetInfo->m_bSuccess;pNetInfo->m_bSuccess = FALSE;}else{success = FALSE;}}return success;}
4)NETINFO結構的定義:
typedef struct tagNetInfo {HINTERNET m_hHandle;BOOL m_bSuccess;HANDLE m_hEvent;tagNetInfo(){m_hHandle = NULL;m_bSuccess = FALSE;m_hEvent = NULL;}}NETINFO;