網絡編程對於很多的初學者來說,都是很向往的一種編程技能,但是很多的初學者卻因為很長一段時間無法進入網絡編程的大門而放棄了對於該部分技術的學習。
在 學習網絡編程以前,很多初學者可能覺得網絡編程是比較復雜的系統工程,需要了解很多和網絡相關的基礎知識,其實這些都不是很必需的。首先來問一個問題:你 會打手機嗎?很多人可能說肯定會啊,不就是按按電話號碼,撥打電話嘛,很簡單的事情啊!其實初學者如果入門網絡編程的話也可以做到這麼簡單!
網絡編程就是在兩個或兩個以上的設備(例如計算機)之間傳輸數據。程序員所作的事情就是把數據發送到指定的位置,或者接收到指定的數據,這個就是狹義的網絡編程范疇。在發送和接收數據時,大部分的程序設計語言都設計了專門的API實現這些功能,程序員只需要調用即可。所以,基礎的網絡編程可以和打電話一樣簡單。
下面就開始Java語言的網絡編程技術學習吧。
網 絡編程技術是當前一種主流的編程技術,隨著聯網趨勢的逐步增強以及網絡應用程序的大量出現,所以在實際的開發中網絡編程技術獲得了大量的使用。本章中以淺 顯的基礎知識說明和實際的案例使廣大初學者能夠進入網絡編程技術的大門,至於以後的實際修行就要閱讀進階的書籍以及進行大量的實際練習。
網絡編程的實質就是兩個(或多個)設備(例如計算機)之間的數據傳輸。
按照計算機網絡的定義,通過一定的物理設備將處於不同位置的計算機連接起來組成的網絡,這個網絡中包含的設備有:計算機、路由器、交換機等等。
其實從軟件編程的角度來說,對於物理設備的理解不需要很深刻,就像你打電話時不需要很熟悉通信網絡的底層實現是一樣的,但是當深入到網絡編程的底層時,這些基礎知識是必須要補的。
路由器和交換機組成了核心的計算機網絡,計算機只是這個網絡上的節點以及控制等,通過光纖、網線等連接將設備連接起來,從而形成了一張巨大的計算機網絡。
網絡最主要的優勢在於共享:共享設備和數據,現在共享設備最常見的是打印機,一個公司一般一個打印機即可,共享數據就是將大量的數據存儲在一組機器中,其它的計算機通過網絡訪問這些數據,例如網站、銀行服務器等等。
如果需要了解更多的網絡硬件基礎知識,可以閱讀《計算機網絡》教材,對於基礎進行強化,這個在基礎學習階段不是必須的,但是如果想在網絡編程領域有所造詣,則是一個必須的基本功。
對於網絡編程來說,最主要的是計算機和計算機之間的通信,這樣首要的問題就是如何找到網絡上的計算機呢?這就需要了解IP地址的概念。
為了能夠方便的識別網絡上的每個設備,網絡中的每個設備都會有一個唯一的數字標識,這個就是IP地址。在計算機網絡中,現在命名IP地址的規定是IPv4協議,該協議規定每個IP地址由4個0-255之間的數字組成,例如10.0.120.34。每個接入網絡的計算機都擁有唯一的IP地址,這個IP地址可能是固定的,例如網絡上各種各樣的服務器,也可以是動態的,例如使用ADSL撥號上網的寬帶用戶,無論以何種方式獲得或是否是固定的,每個計算機在聯網以後都擁有一個唯一的合法IP地址,就像每個手機號碼一樣。
但是由於IP地址不容易記憶,所以為了方便記憶,有創造了另外一個概念——域名(Domain Name),例如sohu.com等。一個IP地址可以對應多個域名,一個域名只能對應一個IP地址。域名的概念可以類比手機中的通訊簿,由於手機號碼不方便記憶,所以添加一個姓名標識號碼,在實際撥打電話時可以選擇該姓名,然後撥打即可。
在網絡中傳輸的數據,全部是以IP地址作為地址標識,所以在實際傳輸數據以前需要將域名轉換為IP地址,實現這種功能的服務器稱之為DNS服務器,也就是通俗的說法叫做域名解析。例如當用戶在浏覽器輸入域名時,浏覽器首先請求DNS服務器,將域名轉換為IP地址,然後將轉換後的IP地址反饋給浏覽器,然後再進行實際的數據傳輸。
當DNS服務器正常工作時,使用IP地址或域名都可以很方便的找到計算機網絡中的某個設備,例如服務器計算機。當DNS不正常工作時,只能通過IP地址訪問該設備。所以IP地址的使用要比域名通用一些。
IP地址和域名很好的解決了在網絡中找到一個計算機的問題,但是為了讓一個計算機可以同時運行多個網絡程序,就引入了另外一個概念——端口(port)。
在介紹端口的概念以前,首先來看一個例子,一般一個公司前台會有一個電話,每個員工會有一個分機,這樣如果需要找到這個員工的話,需要首先撥打前台總機,然後轉該分機號即可。這樣減少了公司的開銷,也方便了每個員工。在該示例中前台總機的電話號碼就相當於IP地址,而每個員工的分機號就相當於端口。
有了端口的概念以後,在同一個計算機中每個程序對應唯一的端口,這樣一個計算機上就可以通過端口區分發送給每個端口的數據了,換句話說,也就是一個計算機上可以並發運行多個網絡程序,而不會在互相之間產生干擾。
在硬件上規定,端口的號碼必須位於0-65535之間,每個端口唯一的對應一個網絡程序,一個網絡程序可以使用多個端口。這樣一個網絡程序運行在一台計算上時,不管是客戶端還是服務器,都是至少占用一個端口進行網絡通訊。在接收數據時,首先發送給對應的計算機,然後計算機根據端口把數據轉發給對應的程序。
有了IP地址和端口的概念以後,在進行網絡通訊交換時,就可以通過IP地址查找到該台計算機,然後通過端口標識這台計算機上的一個唯一的程序。這樣就可以進行網絡數據的交換了。
但是,進行網絡編程時,只有IP地址和端口的概念還是不夠的,下面就介紹一下基礎的網絡編程相關的軟件基礎知識。
按照前面的介紹,網絡編程就是兩個或多個設備之間的數據交換,其實更具體的說,網絡編程就是兩個或多個程序之間的數據交換,和普通的單機程序相比,網絡程序最大的不同就是需要交換數據的程序運行在不同的計算機上,這樣就造成了數據交換的復雜。雖然通過IP地址和端口可以找到網絡上運行的一個程序,但是如果需要進行網絡編程,則還需要了解網絡通訊的過程。
網絡通訊基於“請求-響應”模型。為了理解這個模型,先來看一個例子,經常看電視的人肯定見過審訊的場面吧,一般是這樣的:
警察:姓名
嫌疑犯:XXX
警察:性別
嫌疑犯:男
警察:年齡
嫌疑犯:29
……
在這個例子中,警察問一句,嫌疑犯回答一句,如果警察不問,則嫌疑犯保持沉默。這種一問一答的形式就是網絡中的“請求-響應”模型。也就是通訊的一端發送數據,另外一端反饋數據,網絡通訊都基於該模型。
在網絡通訊中,第一次主動發起通訊的程序被稱作客戶端(Client)程序,簡稱客戶端,而在第一次通訊中等待連接的程序被稱作服務器端(Server)程序,簡稱服務器。一旦通訊建立,則客戶端和服務器端完全一樣,沒有本質的區別。
由此,網絡編程中的兩種程序就分別是客戶端和服務器端,例如QQ程序,每個QQ用戶安裝的都是QQ客戶端程序,而QQ服務器端程序則運行在騰訊公司的機房中,為大量的QQ用戶提供服務。這種網絡編程的結構被稱作客戶端/服務器結構,也叫做Client/Server結構,簡稱C/S結構。
使用C/S結 構的程序,在開發時需要分別開發客戶端和服務器端,這種結構的優勢在於由於客戶端是專門開發的,所以根據需要實現各種效果,專業點說就是表現力豐富,而服 務器端也需要專門進行開發。但是這種結構也存在著很多不足,例如通用性差,幾乎不能通用等,也就是說一種程序的客戶端只能和對應的服務器端通訊,而不能和 其它服務器端通訊,在實際維護時,也需要維護專門的客戶端和服務器端,維護的壓力比較大。
其實在運行很多程序時,沒有必要使用專用的客戶端,而需要使用通用的客戶端,例如浏覽器,使用浏覽器作為客戶端的結構被稱作浏覽器/服務器結構,也叫做Browser/Server結構,簡稱為B/S結構。
使用B/S結構的程序,在開發時只需要開發服務器端即可,這種結構的優勢在於開發的壓力比較小,不需要維護客戶端。但是這種結構也存在著很多不足,例如浏覽器的限制比較大,表現力不強,無法進行系統級操作等。
總之C/S結構和B/S結構是現在網絡編程中常見的兩種結構,B/S結構其實也就是一種特殊的C/S結構。
另外簡單的介紹一下P2P(Point to Point)程序,常見的如BT、電驢等。P2P程序是一種特殊的程序,應該一個P2P程序中既包含客戶端程序,也包含服務器端程序,例如BT,使用客戶端程序部分連接其它的種子(服務器端),而使用服務器端向其它的BT客戶端傳輸數據。如果這個還不是很清楚,其實P2P程序和手機是一樣的,當手機撥打電話時就是使用客戶端的作用,而手機處於待機狀態時,可以接收到其它用戶撥打的電話則起的就是服務器端的功能,只是一般的手機不能同時使用撥打電話和接聽電話的功能,而P2P程序實現了該功能。
最後再介紹一個網絡編程中最重要,也是最復雜的概念——協議(Protocol)。按照前面的介紹,網絡編程就是運行在不同計算機中兩個程序之間的數據交換。在實際進行數據交換時,為了讓接收端理解該數據,計算機比較笨,什麼都不懂的,那麼就需要規定該數據的格式,這個數據的格式就是協議。
如 果沒有理解協議的概念,那麼再舉一個例子,記得有個電影叫《永不消逝的電波》,講述的是地下黨通過電台發送情報的故事,這裡我們不探討電影的劇情,而只關 心電台發送的數據。在實際發報時,需要首先將需要發送的內容轉換為電報編碼,然後將電報編碼發送出去,而接收端接收的是電報編碼,如果需要理解電報的內容 則需要根據密碼本翻譯出該電報的內容。這裡的密碼本就規定了一種數據格式,這種對於網絡中傳輸的數據格式在網絡編程中就被稱作協議。
那麼如何來編寫協議格式呢?答案是隨意。只要按照這種協議格式能夠生成唯一的編碼,按照該編碼可以唯一的解析出發送數據的內容即可。也正因為各個網絡程序之間協議格式的不同,所以才導致了客戶端程序都是專用的結構。
在實際的網絡程序編程中,最麻煩的內容不是數據的發送和接收,因為這個功能在幾乎所有的程序語言中都提供了封裝好的API進行調用,最麻煩的內容就是協議的設計以及協議的生產和解析,這個才是網絡編程中最核心的內容。
關於網絡編程的基礎知識,就介紹這裡,深刻理解IP地址、端口和協議等概念,將會極大的有助於後續知識的學習。
在現有的網絡中,網絡通訊的方式主要有兩種:
1、 TCP(傳輸控制協議)方式
2、 UDP(用戶數據報協議)方式
為 了方便理解這兩種方式,還是先來看一個例子。大家使用手機時,向別人傳遞信息時有兩種方式:撥打電話和發送短信。使用撥打電話的方式可以保證將信息傳遞給 別人,因為別人接聽電話時本身就確認接收到了該信息。而發送短信的方式價格低廉,使用方便,但是接收人有可能接收不到。
在網絡通訊中,TCP方式就類似於撥打電話,使用該種方式進行網絡通訊時,需要建立專門的虛擬連接,然後進行可靠的數據傳輸,如果數據發送失敗,則客戶端會自動重發該數據。而UDP方式就類似於發送短信,使用這種方式進行網絡通訊時,不需要建立專門的虛擬連接,傳輸也不是很可靠,如果發送失敗則客戶端無法獲得。
這兩種傳輸方式都是實際的網絡編程中進行使用,重要的數據一般使用TCP方式進行數據傳輸,而大量的非核心數據則都通過UDP方式進行傳遞,在一些程序中甚至結合使用這兩種方式進行數據的傳遞。
由於TCP需要建立專用的虛擬連接以及確認傳輸是否正確,所以使用TCP方式的速度稍微慢一些,而且傳輸時產生的數據量要比UDP稍微大一些。
關於網絡編程的基礎知識就介紹這麼多,如果需要深入了解相關知識請閱讀專門的計算機網絡書籍,下面開始介紹Java語言中網絡編程的相關技術。
前面介紹了網絡編程的相關基礎知識,初步建立了網絡編程的概念,但是實際學習網絡編程還必須使用某種程序設計語言進行代碼實現,下面就介紹一下網絡編程的代碼實現。
按照前面的基礎知識介紹,無論使用TCP方式還是UDP方式進行網絡通訊,網絡編程都是由客戶端和服務器端組成。當然,B/S結構的編程中只需要實現服務器端即可。所以,下面介紹網絡編程的步驟時,均以C/S結構為基礎進行介紹。
說明:這裡的步驟實現和語言無關,也就是說,這個步驟適用於各種語言實現,不局限於Java語言。
客戶端(Client)是指網絡編程中首先發起連接的程序,客戶端一般實現程序界面和基本邏輯實現,在進行實際的客戶端編程時,無論客戶端復雜還是簡單,以及客戶端實現的方式,客戶端的編程主要由三個步驟實現:
1、 建立網絡連接
客戶端網絡編程的第一步都是建立網絡連接。在建立網絡連接時需要指定連接到的服務器的IP地址和端口號,建立完成以後,會形成一條虛擬的連接,後續的操作就可以通過該連接實現數據交換了。
2、 交換數據
連接建立以後,就可以通過這個連接交換數據了。交換數據嚴格按照請求響應模型進行,由客戶端發送一個請求數據到服務器,服務器反饋一個響應數據給客戶端,如果客戶端不發送請求則服務器端就不響應。
根據邏輯需要,可以多次交換數據,但是還是必須遵循請求響應模型。
3、 關閉網絡連接
在數據交換完成以後,關閉網絡連接,釋放程序占用的端口、內存等系統資源,結束網絡編程。
最基本的步驟一般都是這三個步驟,在實際實現時,步驟2會出現重復,在進行代碼組織時,由於網絡編程是比較耗時的操作,所以一般開啟專門的現場進行網絡通訊。
服務器端(Server)是指在網絡編程中被動等待連接的程序,服務器端一般實現程序的核心邏輯以及數據存儲等核心功能。服務器端的編程步驟和客戶端不同,是由四個步驟實現,依次是:
1、 監聽端口
服務器端屬於被動等待連接,所以服務器端啟動以後,不需要發起連接,而只需要監聽本地計算機的某個固定端口即可。
這個端口就是服務器端開放給客戶端的端口,服務器端程序運行的本地計算機的IP地址就是服務器端程序的IP地址。
2、 獲得連接
當客戶端連接到服務器端時,服務器端就可以獲得一個連接,這個連接包含客戶端的信息,例如客戶端IP地址等等,服務器端和客戶端也通過該連接進行數據交換。
一般在服務器端編程中,當獲得連接時,需要開啟專門的線程處理該連接,每個連接都由獨立的線程實現。
3、 交換數據
服務器端通過獲得的連接進行數據交換。服務器端的數據交換步驟是首先接收客戶端發送過來的數據,然後進行邏輯處理,再把處理以後的結果數據發送給客戶端。簡單來說,就是先接收再發送,這個和客戶端的數據交換數序不同。
其實,服務器端獲得的連接和客戶端連接是一樣的,只是數據交換的步驟不同。
當然,服務器端的數據交換也是可以多次進行的。
在數據交換完成以後,關閉和客戶端的連接。
4、 關閉連接
當服務器程序關閉時,需要關閉服務器端,通過關閉服務器端使得服務器監聽的端口以及占用的內存可以釋放出來,實現了連接的關閉。
其實服務器端編程的模型和呼叫中心的實現是類似的,例如移動的客服電話10086就是典型的呼叫中心,當一個用戶撥打10086時,轉接給一個專門的客服人員,由該客服實現和該用戶的問題解決,當另外一個用戶撥打10086時,則轉接給另一個客服,實現問題解決,依次類推。
在服務器端編程時,10086這個電話號碼就類似於服務器端的端口號碼,每個用戶就相當於一個客戶端程序,每個客服人員就相當於服務器端啟動的專門和客戶端連接的線程,每個線程都是獨立進行交互的。
這就是服務器端編程的模型,只是TCP方式是需要建立連接的,對於服務器端的壓力比較大,而UDP是不需要建立連接的,對於服務器端的壓力比較小罷了。
總之,無論使用任何語言,任何方式進行基礎的網絡編程,都必須遵循固定的步驟進行操作,在熟悉了這些步驟以後,可以根據需要進行邏輯上的處理,但是還是必須遵循固定的步驟進行。
其實,基礎的網絡編程本身不難,也不需要很多的基礎網絡知識,只是由於編程的基礎功能都已經由API實現,而且需要按照固定的步驟進行,所以在入門時有一定的門檻,希望下面的內容能夠將你快速的帶入網絡編程技術的大門。
Java語言是在網絡環境下誕生的,所以Java語言雖然不能說是對於網絡編程的支持最好的語言,但是必須說是一種對於網絡編程提供良好支持的語言,使用Java語言進行網絡編程將是一件比較輕松的工作。
和網絡編程有關的基本API位於java.net包中,該包中包含了基本的網絡編程實現,該包是網絡編程的基礎。該包中既包含基礎的網絡編程類,也包含封裝後的專門處理WEB相關的處理類。在本章中,將只介紹基礎的網絡編程類。
首先來介紹一個基礎的網絡類——InetAddress類。該類的功能是代表一個IP地址,並且將IP地址和域名相關的操作方法包含在該類的內部。
關於該類的使用,下面通過一個基礎的代碼示例演示該類的使用,代碼如下:
package inetaddressdemo;
import java.net.*;
/**
* 演示InetAddress類的基本使用
*/
public class InetAddressDemo {
public static void main(String[] args) {
try{
//使用域名創建對象
InetAddress inet1 = InetAddress.getByName("www.163.com");
System.out.println(inet1);
//使用IP創建對象
InetAddress inet2 = InetAddress.getByName("127.0.0.1");
System.out.println(inet2);
//獲得本機地址對象
InetAddress inet3 = InetAddress.getLocalHost();
System.out.println(inet3);
//獲得對象中存儲的域名
String host = inet3.getHostName();
System.out.println("域名:" + host);
//獲得對象中存儲的IP
String ip = inet3.getHostAddress();
System.out.println("IP:" + ip);
}catch(Exception e){}
}
}
在該示例代碼中,演示了InetAddress類的基本使用,並使用了該類中的幾個常用方法,該代碼的執行結果是: