1. 程式人生 > >淺談如何學習網路程式設計

淺談如何學習網路程式設計

如何學習網路程式設計?這是我的經驗之談,我從來就沒有系統的學習過網路程式設計(非科班麼),學習過程中走了不少彎路。最近在讀經典的《Linux程式設計(第3版)》,第十五章講的是套接字Socket程式設計,讀完之後,產生了一些想法,覺得有必要寫下來。

學習網路程式設計我遇到的主要兩個困惑是:  
    第一:計算機網路中的一個個協議都是抽象的,怎麼和具體實際結合起來呢?   
    第二:知道了socket程式設計的一般步驟後,如何能夠寫成複雜的伺服器程式?(如Web伺服器)

我的學習過程是這樣子的: 
  ●先是利用WinInet函式庫寫了幾個簡單的網路應用程式:簡易登入、查詢新書RSS等;瞭解了HTTP協議的一些內容。  
  ●後來又看了孫鑫的VC視訊教程,

image ,雖然照著視訊能夠寫出例項程式碼來,但是僅僅是會用,其中很多原理都不理解,比如說WSA開頭的非同步函式,Winsock2對socket的一些增強或者改進等。  

  ●後來是一邊上《計算機網路》的課,一邊讀《C++網路程式設計》。通過計算機網路課我知道了所謂的協議分析是怎麼一回事情,通過wireshark抓包分析,“協議”就如同這個詞本身意思是一樣的,是通訊過程中的一種約定,規定了資料包中的每個或每幾個位元組代表了什麼意思;   

  ●至於《C++網路程式設計》,十分慚愧,我最大的收穫不是如何進行網路程式設計,而是ACE框架的設計原則,通過實際的例子明白了設計模式是怎麼一回事情,可以去我的
豆瓣書評
 看看。  
  
● 再後來,偶然的發現了《計算機網路高階程式設計技術》,我初略的翻了翻,看到裡面的基礎、提高、綜合訓練篇、突然反應過來:socket和作業系統提供的系統呼叫,基本上都是C語言介面的,協議欄位的具體表現,不就是用結構體嗎?協議中的幾個位元組代表什麼與C語言基本資料型別就能對應了起來(-_-!這是缺少實踐造成的遲鈍啊)。 

  ●再後來,瞭解了下Boost.asio,Java的MINA框架,這些都是非同步I/O前攝器模式的實現,當然還有ACE_Proactor 

  ●再後來由於參加比賽的需要,飛快的閱讀了《深入理解MySQL核心技術》和Linux程式設計(第3版)》,就這樣從把整個知識體系都聯絡起來,從socket到完整網路伺服器程式,我的網路程式設計才算正式進入了門道。

所以,正常的學習路徑應該是:C/C++語言 -->>計算機網路 -->>協議分析 -->>BSD Socket、OS API ( fork()、pthread_create()、select() ) -->>Reactor、Proactor模式

在這個過程我的體會是,最好是從Linux下或者Unix底下學習,比起Windows,Linux的程式設計介面設計更很簡潔,使用的基本上都是標準的資料型別,很多原始碼是開放的,而且我比較習慣於看小寫的英文單詞。。。我發現,如果最一開始能夠從整體上了解網路程式設計的全景,就會知道應該學習什麼,下一步該學什麼,循序漸進才是好的學習方法。

我所理解的“全景”:

--計算機網路種類有很多種:ATM、X.25、Internet(大大小小的區域網互聯而成,乙太網、令牌網等等)

---- Internet通訊的協議也有很多種,其中最核心的是TCP/IP協議

---- 網路程式設計介面也有很多種,BSD UNIX提出了socket,是一種通訊機制,是管道概念的擴充套件

-------- socket有三種屬性:域(或協議族)、型別、協議

-------- 最常用的協議族有AF_UNIX和AF_INET(對應現在的Internet),AF_INET的型別又有兩種:資料流(tcp)和資料報 (udp)

------------ 在<sys/types.h>和<sys/socket.h>定義了socket程式設計的系統呼叫:socket()、struct sockaddr、bind()、listen()、accept()、connect()、close()、sendto()、recvfrom()

------------ 其中bind()是用來給建立的socket命名的,如果是AF_UNIX會關聯到檔案系統的一個路徑上,如果是AF_INET則會繫結到IP的埠號上;listen()用來儲存未處理的客戶請求的佇列;accept()等待客戶端的連線,會建立新的socket用來處理客戶端連線。

------------ 由於歷史原因,不同的計算機使用不同的位元組序來表示整數,Intel和Motorola的處理器的位元組序就不一樣,所以要轉換為網路序(好像Unicode中的Little-Endian、Big-Endian也是這麼個情況。。)

------------ 伺服器必然為多客戶服務的,為了提高執行效率,高效利用系統資源,就出現多程序、多執行緒的服務端程式,這就需要用到fork()和pthread_create()了,再往下就是select()、pull()等多路複用和非同步I/O機制了。

----------------為了簡化網路應用程式的開發,增加程式碼的複用性、擴充套件性、可謂性;出現了Reacotr、Preactor等設計模式,出現了ACE、Boost.asio等框架、進一步簡化網路開發的難度,出現了WinInet、libcurl這樣的面向應用層的函式庫。

最後我試著回答最開始的兩個問題:

    第一:描述協議基本上是C/C++中的結構體、協議中規定的多少位元組代表什麼,對應中C/C++中的標準資料型別。這是因為作業系統基本上都是用C語言編寫的,提供的介面也是C語言的介面。上層的一些協議如HTTP、SOAP、XMPP基本上純文字的,字串就能表示。

    第二:複雜的伺服器程式複雜之處在於對高效能、執行效率的要求,這就需要利用作業系統提供的一些機制,比如多程序、多執行緒、原生支援的非同步I/O機制。針對軟體開發的複用性等要求,需要利用面向物件的設計思想,分層的思想、設計模式等。

====================================================================================

ps:說實話,自己不是太懂得怎麼學習網路程式設計的,只是接觸過socket套接字,而且不知道怎麼與網路協議聯絡起來,看了這篇文章,大致瞭解了一些。要學習的話,還是先以linux下的為主,window的東西太多坑。