用I/O完成端口+socket編寫客戶端demo實現Http下載

//暫時先把已完成的部分記錄下來,這個demo先暫停下來,這個還沒有實現好的。
最近學習了一些網絡編程的知識,想要在vs2015下實現一個控制檯應用程序,通過命令行啓動,
啓動方式:client url download_path
可以從指定的下載地址把文件下載到本地指定的路徑。


socket下載流程:
1.初始化winscok庫。
2.解析url,根據url規範,一個url地址長這樣:(協議名://)+(主機名)+(:端口號)+(//頁面地址)。
此處需要拿到主機名。
3.通過主機名可以獲取ip地址,有兩種方法,一是通過api獲取,可以通過gethostbyname獲取,但是這個api已經被棄用了,如果要使用要在vs項目屬性->C/C++->預處理器定義 增加_WINSOCK_DEPRECATED_NO_WARNINGS。msdn的建議是使用getaddrinfo這個api,試了一下,會得到一個結構,還沒完全理解清楚,就沒有用(待再次嘗試)。
二是可以通過dns解析,然後獲取,就是像在命令行那裏敲ping+主機名那樣,也可以得到的,但是這個具體原理我還沒完全搞清楚,嘗試了一下失敗了(待再次嘗試)。
4.拿到ip地址之後,http協議默認端口號80。
然後就可以建立連接了,有兩種方式:(阻塞)connect,(非阻塞)ConnectEx。此處使用異步的ConnectEx,需要使用到重疊結構。注意ConnectEx不能像connect那樣直接調用的,是要通過函數指針LPFN_CONNECTEX來使用的。
5.與服務器建立好連接之後,需要向服務器發送一個請求,這裏打算使用異步的WSAsend()
6.發送請求之後可能是立即返回的(之前好像看到說是返回的一般都是失敗的,因爲他還沒完成),這塊還沒了解清楚,之後用WSARecv()收回應。這個時候要解析他迴應的消息,要劃分消息頭和消息體。消息頭的特徵是末尾是\r\n,而消息體是\r\n\r\n。可以遍歷獲取到的迴應然後劃分開。
7.確定消息體的長度。
8.消息體就是要拿的數據,然後要看看數據是不是壓縮過的呀,如果是有content-encoding這個屬性的話它就是被壓縮過的,那麼就需要解壓數據。這個屬性好像是在請求頭可以看到(待…),這塊還沒了解清楚。
9.拿到了數據之後,就保存到本地,這裏是打算直接寫入到本地的文件裏。寫入之前應該判斷一下本地是否存在這個文件,存在就刪掉寫入,不存在就直接創建然後寫入。


I/O完成端口流程:
1.創建I/O完成端口。
2.創建下載要用的那個socket,然後把他和已經創建好的完成端口綁定起來。
3.分別創建讀和寫的重疊結構。
4.創建工作者線程。這個線程是完成整個下載的邏輯的。裏面是一個循環,處理包括收發數據的邏輯,它是一直進行的,直到收到退出消息。
5.當完成了下載之後,就在隊列裏面投遞一個完成封包,然後就告訴線程,完成啦你來處理數據吧!但是因爲是異步的所以會立即返回(好像是這樣),這時要判斷是不是pending,就是它是不是還沒完成呀,沒完成就做完了再處理!這裏好像是可以設置一個超時把,如果超時了就不幹啦!想設置成要是超過10分鐘沒有下載速度的話就取消下載。
6.處理完數據之後釋放資源。卸載庫。


參考:
基於TCP的Socket 編程
完成端口詳解
IOCP模型與網絡編程
Windows環境下用C++實現socket編程
IOCP淺析與實例
比較兩種設計模式:reactor和proactor
(參考這篇文章是因爲之前不知道在哪裏看到說windows的完成端口其實就是proactor的實現,所以就看了這個)
C++ new的nothrow關鍵字和new_handler用法
(這個是一個細節的問題,所以也想把這篇文章鏈接貼出來方便以後查閱)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章