WinInet库之FTP通信
生活随笔
收集整理的這篇文章主要介紹了
WinInet库之FTP通信
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
// 文件傳輸協議(File Transfer Protocol,簡稱FTP)用在互聯網上文件的雙向傳輸,是主用于文件的上傳和下載處理的協議。
// 上傳是指將文件從本地計算機中復制到遠程主機上。下載是指將遠程主機上的文件復制到本地計算機上。
// FTP是專門為文件傳輸而生的,傳輸效率高,穩定性好。公司內部通常會有多個FTP服務器,用于共享公司內部的資料。// 在Windows上,微軟提供了WinInet(即Windows Internet)庫用于方便網絡程序的開發。WinInet支持FTP、HTTP(s)、Gopher類型的網絡開發。
// 也就是有專門的WIN32 API函數。// PS:InternetOpen函數:
// 功能:初始化一個應用程序,以使用WinInet函數。
// 原型:HINTERNET InternetOpen(
// _In_ LPCTSTR lpszAgent,
// _In_ DWORD dwAccessType,
// _In_ LPCTSTR lpszProxyName,
// _In_ LPCTSTR lpszProxyBypass,
// _In_ DWORD dwFlags
// )
// 參數:lpszAgent:指定調用WinInet函數的應用程序或實體的名稱,也就是給定一個字符串,用于標識這個程序。
// dwAccessType:訪問類型,參數可以是以下值之一:
// INTERNET_OPEN_TYPE_DIRECT:直接連接網絡(不使用代理)
// INTERNET_OPEN_TYPE_PRECONFIG:獲取代理或者直接從注冊表中獲取的配置,使用代理連接網絡
// INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY:獲取代理或者直接從注冊表中獲取的配置,并防止啟用Microsoft JScript或互聯網設置(INS)文件的使用
// INTERNET_OPEN_TYPE_PROXY:通過代理來請求,除非代理旁路列表中提供的名稱解析繞過代理。在這種情況下,使用該功能。
// lpszProxyName:指定代理服務器的名稱,如果dwAccessType為INTERNET_OPEN_TYPE_PROXY,則此參數應當設置為NULL
// lpszProxyBypass:指定可選列表的主機名或IP地址。如果dwAccessType設置為INTERNET_OPEN_TYPE_PROXY,則此參數省略為NULL
// dwFlags:可以是以下值的組合:
// INTERNET_FLAG_ASYNC:異步請求
// INTERNET_FLAG_FROM_CACHE:不進行網絡請求,從緩存中返回所有實體。
// INTERNET_FLAG_OFFLINE:與INTERNET_FLAG_CACHE相同,不發出網絡請求,所有實體都從緩存中返回。
// 結果:成功,返回一個有效的句柄,失敗,返回NULL。// PS:InternetConnect函數
// 功能:建立互聯網的連接。
// 原型:HINTERNET WINAPI InternetConnect(
// HINTERNET hInternet,
// LPCTSTR lpszServerName,
// INTERNET_PORT nServerPort,
// LPCTSTR lpszUserName,
// lPCTSTR lpszPassword,
// DWORD dwService,
// DWORD dwFlags,
// DWORD dwContext
// )
// 參數:hInternet:由InternetOpen函數返回的句柄。
// lpszServerName:連接的IP或主機名。
// nServerPort:連接的端口。
// lpszUserName:用戶名,沒有則設置NULL。
// lpszPassword:密碼,沒有則設置為NULL。
// dwService:使用的服務器類型,可以使用以下值之一:
// INTERNET_SERVICE_FTP = 1:連接到一個FTP服務器上。
// INTERNET_SERVICE_GOPHER = 2:連接到一個Gopher服務器上。
// INTERNET_SERVICE_HTTP = 3:連接到一個HTTP服務器上。
// dwFlags:文件傳輸形式及緩存標記,一般置零。
// dwContext:置為零。
// 結果:成功返回非零,失敗返回零。// PS:FtpOpenFile函數:
// 功能:訪問FTP服務器上的遠程文件以執行讀取或寫入操作。
// 原型:HINTERNET FtpOpenFile(
// _In_ HINTERNET hConnect,
// _In_ LPCTSTR lpszFileName,
// _In_ DWORD dwAccess,
// _In_ DWORD dwFlags,
// _In_ DWORD_PTR dwContext
// )
// 參數:hConnect:由InternetConnect返回的句柄。
// lpszFileName:要訪問的文件名。通常是URL+文件后綴
// dwAcess:可以是GENERIC_READ或者GENERIC_WRITE,但不能同時擁有。
// dwFlags:傳輸類型,可以是以下值之一:
// FTP_TRANSFER_TYPE_ASCII:使用FTP的ASCII傳輸方法。
// FTP_TRANSFER_TYPE_BINARY:使用FTP的圖像傳輸方法傳輸文件,也就是二進制方式。
// FTP_TRANSFER_TYPE_UNKNOWN:默認使用FTP_TRANSFER_TYPE_BINARY。
// INTERNET_FLAG_TRANSFER_ASCII:以ASCII格式傳輸文件。
// INTERNET_FLAG_TRANSFER_BINARY:將文件作為二進制文件進行傳輸。
// 控制文件的緩存,使用以下值之一:
// INTERNET_FLAG_HYPERLINK:強制重新加載。
// INTERNET_FLAG_NEED_FILE:如果無法緩存文件,則會創建臨時文件。
// INTERNET_FLAG_RELOAD:強制從源服務器下載所請求的文件、對象或目錄列表,而不是從緩存中下載。
// INTERNET_FLAG_RESYNCHRONIZE:如果資源資上次現在依賴已被修改,則請重新加載HTTP資源。
// dwContext:置零。
// 結果:成功返回一個句柄,失敗返回NULL。// PS:InternetWriteFile函數:
// 功能:將數據寫入打開的互聯網文件。
// 原型:BOOL InterneetWriteFile(
// _In_ HINTERNET hFile,
// _In_ LPVOID lpBuffer,
// _In_ DWORD dwNumberOfBytesToWrite,
// _Out_ LPDWORD lpdwNumberOfBytesWrite
// )
// 參數:hFile:由FtpOpenFile函數返回的互聯網文件句柄。
// lpBuffer:緩存區,要上傳文件的數據。
// dwNumberOfBytesToWrite:緩存區大小。
// lpdwNumberOfBytesWrite:接收寫入的字節量。
// 結果:成功,返回TRUE,失敗,返回FALSE。// PS:InternetReadFile函數:
// 功能:從打開互聯網文件中讀取數據。
// 原型:BOOL InternetReadFile(
// _In_ HINTERNET hFile,
// _Out_ LPVOID lpBuffer,
// _In_ DWORD dwNumberOfBytesToRead,
// _Out_ LPDWORD lpdwNumberOfBytesRead
// )
// 參數:hFile:由FtpOpenFile函數打開的互聯網文件的句柄。
// lpBuffer:接收數據的緩存區。
// dwNumberOfBytesToRead:預讀取數據的字節量。
// lpdwNumberOfBytesRead:讀取字節量的變量。
// 結果:成功,返回TRUE,失敗返回FALSE。// FTP的URL格式:FTP://賬號:密碼@主機/子目錄或文件。示例:ftp://admin:123456@192.168.0.1/mycode/520.zip。// PS:基于WinInet庫的FTP文件上傳的流程如下:
// 1.首先,調用InternetCrackUrl函數對URL進行分解,從URL中獲取后續操作需要的信息。比如用戶名、密碼、host等。
// 2.調用InternetOpen初始化WinInet庫,建立網絡會話,獲取會話句柄。
// 3.調用INternetConnect與服務器建立連接,并設置FTP數據傳輸方式。
// 4.調用FtpOpenFile函數,根據文件路徑,以GENERIC_WRITE的方式創建文件,并獲取服務器上的文件句柄。
// 5.調用InternetWriteFile函數把本地數據寫入到互聯網文件中,實現文件上傳功能。
// 6.關閉打開的句柄,釋放緩存區資源。// PS:示例代碼:// FTP文件上傳BOOL Ftp_Upload(char* pszUploadUrl, BYTE* pUploadData, DWORD dwUploadDataSize)
{// 變量(略)// 分解URLif (FALSE == Ftp_UrlCrack(pszUploadUrl, szScheme, szHostName, szUserName, szPassword, szUrlPath, szExtraInfo, MAX_PATH)){return FALSE;}// 拼接文件路徑if (0 < ::lstrlen(szExtraInfo)){::lstrcat(szUrlPath, szExtraInfo);}do {// 建立會話hInternet = ::InternetOpen("FTP upload v1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if (NULL == hInternet){Ftp_ShowError("InternetOpen");break;}// 建立會話hConnect = ::InternetConnect(hInternet, szHostName, szUserName, szPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);if (NULL == hConnect){::InternetCloseHandle(hInternet);Ftp_ShowError("InternetConnect");break;}// 打開FTP文件,與本地文件操作類似hFile = ::FtpOpenFile(hConnect, szUrlPath, GENERIC_WRITE, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL);if (NULL == hFile){::InternetCloseHandle(hInternet);::InternetCloseHandle(hConnect);Ftp_ShowError("FtpOpenFile");break;}// 上傳數據bRet = ::InternetWriteFile(hFile, pUploadData, dwUploadDataSize, &dwBytesReturn);if (FALSE == bRet){::InternetCloseHandle(hInternet);::InternetCloseHandle(hConnect);::InternetCloseHandle(hFile);Ftp_ShowError("InternetWriteFile");break;}} while (FALSE);// 釋放內存并關閉句柄(略)return bRet;
}// PS:基于WinInet的FTP文件下載步驟如下:
// 1.使用InternetCrackUrl分解URL,獲取用于后續操作需要的信息。
// 2.調用InternetOpen函數初始化WinInet庫,建立會話,獲取會話句柄。
// 3.調用InternetOpen函數與FTP服務器建立連接,獲取連接句柄。
// 4.調用FtpOpenFile函數,打開互聯網文件,獲取其句柄。
// 5.調用FtpGetFileSize函數獲取文件大小,并根據文件大小申請緩存區,用于存儲文件數據。
// 6.調用InternetReadFile函數,讀取互聯網文件數據到緩存區中,采用循環讀取的方式。
// 7.關閉打開的句柄,進行清理工作。// PS:示例代碼:// FTP文件下載BOOL Ftp_Download(char* pszDownloadUrl, BYTE** ppDownloadData, DWORD* pdwDownloadDataSize)
{// 變量(略)// 分解URLif (FALSE == Ftp_UrlCrack(pszDownloadUrl, szScheme, szHostName, szUserName, szPassword, szUrlPath, szExtraInfo, MAX_PATH)){return FALSE;}// 拼接文件路徑if (0 < ::lstrlen(szExtraInfo)){::lstrcat(szUrlPath, szExtraInfo);}do{// 建立會話hInternet = ::InternetOpen("Ftp Download v1.0", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);if (NULL == hInternet){Ftp_ShowError("InternetOpen");break}// 建立連接hConnect = ::InternetConnect(hInternet, szHostName, INTERNET_INVALID_PORT_NUMBER, szUserName, szPassword, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE, 0);if (NULL == hConnect){::InternetCloseHandle(hInternet);Ftp_ShowError("InternetConnect");break;}// 打開FTP文件hFile = ::FtpOpenFile(hConnect, szUrlPath, GENERIC_READ, FTP_TRANSFER_TYPE_BINARY | INTERNET_FLAG_RELOAD, NULL);if (NULL == hFile){::InternetCloseHandle(hInternet);::InternetCloseHandle(hConnect);Ftp_ShowError("FtpOpenFile");break;}// 獲取文件大小dwDownloadDataSize = ::FtpGetFileSize(hFile, NULL);// 申請動態空間pDownloadData = new BYTE[dwDownloadDataSize];if (NULL == pDownloadData){break;}::RtlZeroMemory(pDownloadData, dwDownloadDataSize);// 申請一個小空間,用于循環接收數據pBuf = new BYTE[dwBufSize];if (NULL == pBuf){break;;}// 循環接收數據do{::RtlZeroMemory(pBuf, dwBufSize);// 接收數據bRet = ::InternetReadFile(hFile, pBuf, dwBufSize, &dwBytesReturn);if (FALSE == bRet){Ftp_ShowError("InternetReadFile");break;}// 拷貝數據::RtlCopyMemory((PVOID)(pDownloadData + dwOffset), pBuf, dwBytesReturn);// 更新數據dwOffset += dwBytesReturn;} while (dwOffset < dwDownloadDataSize);} while (FALSE);// 返回數據**pDownloadData = pDownloadData;*pdwDownloadDataSize = dwDownloadDataSize;// 關閉句柄,釋放內存(略)return bRet;
}
總結
以上是生活随笔為你收集整理的WinInet库之FTP通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个人也挺好的
- 下一篇: 计算机管理控制台损坏,电脑开机提示“WI