一、概述
TCP提供的網絡通訊接口與用戶數據報協議(UDP)截然不同。TCP的特性使網絡編程很具魅力,而且它刪除了UDP的很多干擾部分(例如數據包的排序和丟失),簡化了網絡通訊。UDP關心的是數據包的傳輸,而TCP關注的是建立網絡連接,並在網絡連接中發送和接收字節流。 數據包可以通過網絡用多種方法發送,並且它們到達的時間可能不同。這有利於性能的提高和程序的健壯性,因為單個包的丟失不一定干擾其它包的傳輸。但是,這樣的系統使程序員必須作更多的工作,他們必須保證數據的送達(delivery)。TCP通過對發送和次序的保證消除了這些額外的工作,為客戶端和支持兩路(two-way)通訊的服務器之間提供了可靠的字節通訊流。它在兩台計算機之間建立了"虛擬連接",可以通過虛擬連接發送數據流。
TCP使用更低層的(lower-level)的IP通訊協議在兩台計算機之間建立連接。這種連接提供了一個允許字節流發送和接收的接口,並且采用透明的方式把數據轉換為IP數據報。數據報(datagram)的問題之一是不能保證數據包到達目的地。TCP解決了這個問題,它提供了有保證的數據字節的送達。當然,網絡錯誤影響了送達也是可能的,但是TCP通過類似重新發送數據包解決了這種實現的問題,並且只在情況很嚴重(例如沒有到網絡主機的路由或連接丟失了)的時候才提醒程序員。
兩台計算機之間的虛擬連接表現為套接字(socket)。套接字允許數據的發送和接收,但是UDP套接字和TCP套接字之間有本質的區別。首先TCP套接字連接到單個計算機,然而UDP套接字可以向多台計算機傳輸或接收數據;其次,UDP套接字只能發送和接收數據包,然而TCP允許通過字節流的數據傳輸(表現為輸入流(InputStream)和輸出流(OutputStream))。為了在網絡上傳輸,它們被轉換為數據包,不需要程序員干涉。
1、 UDP(用戶數據報協議)上的TCP的優點
⑴自動化地錯誤控制
TCP流上的數據傳輸比通過UDP的信息包的傳輸更可靠。在TCP下層,通過虛擬連接發送的數據包括一個檢查機制以確保它們沒有被破壞(與UDP類似)。但是,TCP保證了數據的送達--在傳輸過程中丟失的數據包將被重新傳輸。
你也許想知道這是如何實現的--實際上,IP和UDP不保證送達,當數據包丟失的時候它們也不會發出任何警告。在TCP使用數據包發送了某個數據集合的時候就會啟動一個計時器。在UDP中,我們使用 DatagramSocket.setSoTimeout為receive()操作啟動一個計時器。在TCP中,如果接收者發送一個肯定的應答就禁止計時器,但是如果在超時前還沒有收到肯定的應答,數據包就被重新傳輸。這意味著寫入某個TCP套接字的任何數據將到達另一方而不需要程序員的進一步干涉(除非發生大的事故造成整個網絡癱瘓)。錯誤控制的代碼都由TCP處理了。
⑵可靠性
因為在TCP連接中有多方參與的兩台計算機之間發送的數據通過IP數據報傳輸,數據包到達的次序可能經常出現不同。這可能需要使用一個循環從TCP套接字讀取信息,因為字節流的次序可能被打亂並且頻繁遇到不可靠的問題。幸運的是,次序等問題已經被TCP處理好了--每一個數據包都包含一個用於排序的序列號。後發送、先到達的數據包將保持在一個隊列中,直到排好次序的數據可以使用為止。接著數據就可以通過套接字的接口傳遞到應用程序中。
⑶易於使用
盡管把信息存儲為數據包的確沒有超越程序員的范圍,但這不會是計算機之間通訊的最高效率的途徑。還應該有另外一些的復雜性,你可以討論在某個底線之上設計和建立軟件,為程序員提供足夠的復雜性。典型情況下開發者歡迎軟件開發復雜性的降低,TCP就實現了這種功能。TCP允許程序員用一種完全不同的方式思考問題,而這種方式更加現代化。數據不是被處理為不連續的單元(數據報包),而是被處理為連續的流,就像目前讀者所熟悉的I/O流。TCP套接字延續了傳統的Unix編程,在Unix編程中通訊與文件輸入和輸出是一樣處理的。無論開發者寫入網絡套接字、通訊管道、數據結構、用戶控制台或文件的時候,這種機制都時相同的。當然它也同樣應用與讀取信息。這使得通過TCP套接字進行通訊比通過數據報包通訊更加簡單。
2、使用端口在應用程序之間通訊
很明顯,TCP與UDP之間差別巨大,但是在兩種協議之間也有一項重要的相似性。兩種都共享了通訊端口的概念,它可以區別各個應用程序。在相同的端口上可以運行多個服務和客戶端,而且希望不給它們分配端口號而挑選出某個應用程序是不可能的。當TCP套接字建立到某台計算機的連接的時候,它需要兩部分非常重要的信息才能連接到遠程客戶端--該計算機的IP地址和端口號。此外,本地的IP地址和端口號也將綁定到它上面,因此遠程計算機能夠識別是哪一個應用程序建立了連接。總之,你不會希望你自己的電子郵件被在相同系統上運行軟件的其它用戶訪問。
本地端口識別了其它程序建立的到某個應用程序的連接,
允許多個TCP應用程序在同一台計算機上運行
TCP中的端口與UDP中的端口相似--它們的數字范圍都是1-65535。1024以下的端口是受限制的,只能被知名的服務(例如HTTP、FTP、SMTP、POP3和telnet)使用。表1列舉了一些知名的服務以及與它們對應的端口。
表1:協議和與它們相關的端口
知名的服務 服務端口
Telnet 23
SMTP(簡單郵件傳輸協議) 25
HTTP(超文本傳輸協議) 80
POP 3 110
3、套接字操作
TCP套接字可以執行多種操作,包括:
建立到某個遠程主機的連接。
給遠程主機發送數據。
從遠程主機接收數據。
關閉連接。
此外還有一些特殊類型的套接字,它們提供綁定到特定端口號的服務。這類套接字通常用在服務器中,可以執行下面一些操作:
綁定到某個本地端口
從遠程主機接收輸入的連接
從本地端口取消綁定。
這兩種套接字可以被分為不同的類,要麼是客戶端使用的,要麼是服務器使用的(由於某些客戶端可以象服務器一樣操作,還有些服務器可以象客戶端一樣操作)。但是,客戶端和服務器的角色還是可以靠經驗區分的。
二、TCP和客戶端/服務器范型
在網絡編程中(同樣在其它形式的通訊中,例如數據庫編程),使用套接字的應用程序也被分為兩類--客戶端程序和服務器程序。你可能對"客戶端/服務器編程"術語比較熟悉,盡管這個術語的准確意思你不一定清楚。下面的范例就是討論這個主題。
1、 客戶端/服務器范型
客戶端/服務器范型把軟件分為兩類--客戶端程序和服務器程序。客戶端軟件啟動一個連接並發送請求,而服務器軟件監聽連接並處理請求。在UDP編程環境中,沒有建立實際的連接,並且UDP應用程序可以在相同的套接字上建立並接收請求。在TCP環境中,兩台計算機之間建立了連接,客戶端/服務器范型是相對應的。
當軟件作為客戶端或者服務器的時候,它嚴格地定義了角色以更容易適應我們所熟悉的思維模型。軟件要麼啟動請求,要麼處理請求。在兩種角色之間切換使系統更加復雜。即使允許切換,在某個特定的時刻軟件程序也只能是客戶端,而另一個必須是服務器。如果兩個同時是客戶端,就沒有服務器處理請求了。
客戶端/服務器范型是一個重要的理論概念,它廣泛用於實際應用程序中。目前也有其它的通訊模型,例如對等(peer to peer)模型,在這種模型中每一方都可以啟動通訊。但是客戶端/服務器概念是更加流行的選擇,因為它很簡單並且在多數網絡編程中使用。
2、網絡客戶端
網絡客戶端啟動連接,通常處理網絡事務。服務器程序用於實現客戶端的請求--客戶端不用實現服務器的請求。盡管客戶端處於控制地位,但是服務器端仍然有一些功能。客戶端可以要求服務器刪除本地文件系統的所有文件,但是服務器並不是必須執行這個任務的。
網絡客戶端使用雙方都同意的通訊標准(即網絡協議)與服務器對話。例如HTTP客戶端使用的命令組就與郵件客戶端使用的不同,而且目的也完成不同。把 HTTP連接到郵件服務器,或郵件客戶端連接到HTTP服務器,要麼會出現一個錯誤消息,要麼出現一個客戶端不能理解的錯誤消息。因為這個原因,作為協議規格的一部分,必須使用某個端口號,這樣客戶端才能定位服務器。Web服務器通常運行在80端口上,而其它一些服務器可能運行在非標准的端口上,URL的習慣是不列出端口的,它假定使用80端口。
3、網絡服務器
網絡服務器的角色是綁定某個特定的端口(客戶端使用它定位服務器),並且監聽新的連接。盡管客戶端是臨時的,並且只有在用戶選中的時候才運行,但是服務器程序必須不間斷地運行(即使實際上沒有已連接的客戶端),期望某個客戶端在某個時刻需要該服務。服務器程序通常作為數據自適應監視器進程引用,使用Unix用法。它持久的運行,而且一般在該服務器程序的主機啟動時啟動。因此服務器一直等待,直到某個客戶端建立到該服務器端口的連接。有些服務器程序在某個時刻只能處理單個連接,其它一些服務器程序可以通過使用多線程同時處理多個連接。
當開始連接後,服務器就服從客戶端。它等待客戶端發送請求,並且"忠實地"處理它們(可是服務器可以響應錯誤信息,特別是當請求違反某些重要地協議規則或有安全風險的時候)。某些協議(例如HTTP/1.0)通常在每個連接中只允許一個請求,而其它一些協議(例如POP3)支持一系列請求。服務器可以通過發送響應或錯誤消息應答客戶端的請求。學習新的網絡協議(編寫客戶端或服務器)與學習一種新的語言相似,只是語法改變了。但是典型情況下,它的命令的數量更小,