標籤:網路編程 socket serversocket datagramsocket
第十二章 Java網路編程入門
Java提供的三大類網路功能:
(1)URL和URLConnection:三大類中最進階的一種,通過URL網路資源表達方式,可以很容易確定網路上資料的位置。利用URL的表示和建立,Java程式可以直接讀入網路上所放的資料,或把自己的資料傳送到網路的另一端。
(2)Socket:又稱“通訊端”,用於描述IP地址和連接埠(在Internet中,網路中的每台主機都有一個唯一的IP地址,而每台主機又通過提供多個不同連接埠來提供多種服務)。在客戶/伺服器網路中,當客戶機中啟動並執行應用程式(如網頁瀏覽器)需要訪問網路中的伺服器時,客戶機會被臨時分配一個Socket,然後它會通過伺服器的Socket向伺服器發出請求。簡而言之,網路中的資料的發送和接收都是通過Socket來完成的,Socket就像一個檔案控制代碼(讀寫檔案時的一個唯一的順序號),使用者可以通過讀寫Socket來完成客戶機、伺服器之間的通訊。
(3)Datagram:三大類中最低級的一種。其他網路資料傳送方式都假想在程式執行時建立一條安全穩定的通道,但是以Datagram方式傳送資料時,只是把資料的目的地記錄在資料包中,然後就直接放在網路上進行傳輸。系統不保證資料一定能安全送達,也不能確定什麼時候可以送到。也就是說,Datagram不能保證傳送品質。
瞭解Java網路編程基礎知識
(1)網路編程中有兩個主要問題:如何準確定位網路上的一台或多台主機,以及找到主機後如何可靠地、高效地進行資料轉送。在TCP/IP網路通訊協定中,IP地址可以唯一確定Internet上的一台主機,而TCP則提供可靠的資料轉送機制。
(2)TCP/IP協議(傳輸控制通訊協定/網際網路互聯協議 網路通訊協定)
TCP/IP協議是Transmission Control Protocol/Internet Protocol的縮寫,是Internet最基本的協議,是供已串連網際網路的電腦進行通訊的通訊協定。其定義了電子裝置(如電腦)如何連入網際網路,以及資料如何在它們之間傳輸的標準。TCP/IP協議由網路層IP協議和傳輸層的TCP協議組成。
電腦網路通訊劃分為七層,自下而上分別是:物理層,資料連結層,網路層,傳輸層,會話層,展示層,應用程式層。每一層都提供了不同的網路通訊協定。
TCP/IP使用用戶端/伺服器模式進行通訊,且通訊是點對點的,即通訊是在網路中的兩台主機之間進行的。TCP協議為傳輸控制通訊協定,負責聚集資訊或把檔案拆分成更小的包。這些包通過網路傳送到接收端的TCP層,接收端的TCP層把包還原為原始檔案。IP協議是網際協議,負責處理每個包的地址部分,使這些包能正確到達目的地。網路上的網關電腦根據資訊的地址來進行路由選擇。即使來自同一檔案的分包路由也有可能不同,但最後會在目的地匯合。
TCP協議與UDP協議(傳輸層)
(1)TCP協議:連線導向,可靠傳輸。用戶端與伺服器之間必須先建立串連才能進行通訊。得到一個順序的、無差錯的資料流。可以傳輸大容量資料,並確保伺服器正確地接收到用戶端發送的全部資料。
(2)UDP協議:User Datagram Protocol(使用者資料包通訊協定),一種面向無串連,不可靠的傳輸協議。它將資訊封裝成資料報進行傳輸,資料報中包含完整的源地址或目的地址。不能保證資料報是否到達目的地、到達目的地的時間以及內容的正確性。傳輸資料大小限定在64KB之內。
IP地址
Java中用InetAddress類來描述IP地址。這個類沒有公用的構造方法,但是它提供了三個用來獲得InetAddress對象的靜態方法。分別是:
InetAddress getLocalHost():返回一個本地主機的InetAddress對象。
InetAddress getByName(String host):返回主機名稱host指定的InetAddress對象。
InetAddress[] getAllByName():對於某個多IP地址主機,可用該方法得到一個IP地址數組。
此外,InetAddress類還提供了以下方法:
String getHostAddress();返回IP地址字串。
String getHostName();返回主機名稱。
例如:
public class InetAddressTest{
public static void main(String[] args){
InetAddress ia;
ia = InetAddress.getLocalHost(); //獲得本地主機的InetAddress對象
String localHostAddress = ia.getHostAddress(); //獲得本地主機IP地址
String localHostName = ia.getHostName() //獲得本地主機名稱
ia = InetAddress.getByName("www.baidu.com"); //獲得百度網主機的InetAddress對象
String bdHostAddress = ia.getHostAddress(); //擷取百度網主機地址
String bdHostName = ia.getHostName(); //擷取百度網主機名稱
}
}
連接埠
連接埠是為了在一台主機上提供更多的網路資源而採取的一種手段。只有通過IP地址和連接埠號碼才能唯一地確定網路通訊中的進程。連接埠用連接埠號碼來標記,連接埠號碼用0~65535的整數表示。
使用URL訪問網路資源
(1)URL:Uniform Resource Locator(統一資源定位器),對Internet資源的一個引用。大多數情況下,資源表示為一個檔案,如一個HTML文檔,一個影像檔,或一個聲音片段等。因此,可以將URL理解為一個Internet資源地址。通用格式如下:
<PROTOCOL>://<HOSTNAME:PORT>/<PATH>/<FILE>
PROTOCOL表示Internet協議,常用的有HTTP、FTP、SMTP等。HOSTNAME表示資源所在的Internet主機名稱。主機名稱和IP地址是一一對應的,通過網域名稱解析可以由主機名稱得到IP地址。PORT表示連接埠號碼,每一個Internet協議都有自己對應的連接埠號碼。PATH和FILE分別表示資源的路徑名和檔案名稱。
(2)建立URL對象
Java中可以使用URL類訪問Internet資源。URL類的構造方法如下:
a. URL(String spec):使用表示URL地址的字串spec建立URL對象。例如:
URL url = new URL("http://www.sina.com.cn");
b. URL(URL baseURL,String relativeURL):使用絕對位址baseURL與相對位址relativeURL建立URL對象。例如:
URL baseURL = new URL("http://www.base.edu.cn");
URL url = new URL(baseURL,"/library/library.htm");
c. URL(String protocol,String hostName,int port,String fileName):使用網路通訊協定protocol、主機名稱hostName、連接埠號碼port、檔案名稱fileName建立URL對象。例如:
URL url = new URL("http","www.baidu.com","80","/library/library.htm");
d. URL(String protocol,String hostName,String fileName):使用網路通訊協定protocol、主機名稱hostName、檔案名稱fileName建立URL對象。例如:
URL url = new URL("http","www.baidu.com","/library/library.htm");
備忘:URL類的構造方法會拋出非運行時異常MalformedURLException,程式需要對此進行處理。
直接通過URL對象讀取內容
成功建立一個URL對象後,可以調用openStream()方法從網路資源中讀取內容。例如:
public class OpenStreamTest{
public static void main(String[] args){
try{
URL sina = new URL("http://www.sina.com.cn/");
DataInputStream dis = new DataInputStream(sina.openStream());
String readLine;
while((readLine = dis.readLine())!=null){
System.out.print(readLine);
}
dis.close();
}catch(MalformedURLException me){
System.out.print("MalformedURLException:"+me);
}catch(IOException ioe){
System.out.print("IOException:"+ioe);
}
}
}
8. 建立一個URL串連並從中讀取內容
通過URL類的openStream()方法,只能從網路資源中讀取資料。如果想同時對資料進行讀寫操作,則必須利用URLConnection類建立一個URL串連。當與一個URL對象建立串連時,首先要通過URL對象的openConnection()方法產生URLConnection對象。URLConnection對象表示Java程式和URL對象在網路上的通訊串連。如果串連過程失敗,將會產生IOException。例如:
public class URLConnectionTest{
public static void main(String[] args){
try{
URL baidu = new URL("http://www.baidu.com/");
URLConnection conn = baidu.openConnection();
//建立資料輸入流
DataInputStream dis = new DataInputStream(baidu.getInputStream);
String inputLine;
while((inputLine = dis.readLine())!=null){
System.out.print(inputLine);
}
dis.close();
}catch(MalformedURLException me){
System.out.print("MalformedURLException:"+me);
}catch(IOException ioe){
System.out.print("IOException:"+ioe);
}
}
}
9. 使用Socket進行網路通訊
在應用程式層通過傳輸層進行資料通訊時,TCP或UDP協議會遇到同時為多個應用程式進程提供並發服務的問題。多個TCP串連或多個應用程式進程可能需要通過同一個連接埠傳輸資料。為了區別不同的應用程式進程或串連,電腦作業系統為應用程式與TCP/IP協議互動提供了稱為通訊端(Socket)的介面。每個Socket由IP地址、傳輸層協議(TCP或UDP)、連接埠號碼三個參數唯一確定。
使用Socket進行伺服器/用戶端的通訊時,可以分為三個步驟:伺服器監聽,用戶端請求,串連確認。
(1)伺服器監聽:伺服器端Socket即時監聽某個連接埠是否有串連請求。
(2)用戶端請求:指由用戶端的Socket提出串連請求,要串連的目標是伺服器端的Socket。用戶端的Socket首先需要描述它要已連線的服務器端的Socket,指出伺服器端Socket的IP地址和連接埠號碼,然後便可以向伺服器端發送串連請求。
(3)串連確認:當伺服器端的Socket監聽到或者接收到用戶端Socket的串連請求時,就響應用戶端的請求,並建立一個新的線程,然後把伺服器端的Socket的描述發送給用戶端。一旦用戶端確認了此描述,一個串連便建立起來了。而伺服器端Socket繼續處於監聽狀態,並接收其他用戶端Socket的串連請求。
(4)常見的Socket主要分為兩種:
a. 流式Socket:一種基於TCP協議的通訊,即在通訊開始之前先由通訊雙方確認身份並建立一條串連通道,然後通過這條通道傳輸資料。
b. 資料報Socket:一種基於UDP協議的通訊,無需通訊雙方建立串連,而是直接將資訊打包傳向指定的目的地。
(5)流式Socket編程
java.net包中定義了Socket類和ServerSocket類,它們是實現流式Socket通訊的主要工具。建立Socket對象就建立了一個用戶端與伺服器端的串連,而建立一個ServerSocket對象就建立了一個監聽服務。
a. Socket類:通過構造一個Socket對象可以建立用戶端與伺服器的串連。Socket類的構造方法如下:
Socket(String host,int port)
Socket(InetAddress address,int port)
Socket(InetAddress address,int port,InetAddress localAddr,int localPort)
其中,host、port和address分別表示串連主機的主機名稱、連接埠號碼和IP地址;locaAddr表示本地主機的IP地址;localPort表示本地主機連接埠號碼。例如:
Socket mySocket = new Socket("www.sina.com",3000);
備忘:每一個連接埠號碼提供一種特定的服務,只有給出正確的連接埠,才能獲得相應的服務。0~1023的連接埠號碼為系統保留,例如,http服務的連接埠號碼為80,telenet服務的連接埠號碼為23,ftp服務連接埠號碼為21。
建立一個新的Socket對象後,就可以使用其getInputStream()方法獲得一個InputStream流,然後可以通過InputStream對象從某個主機接收資訊;而使用getOutputStream()可以獲得一個OutputStream對象,利用它可以發送資訊到某個主機。例如:
public class GetDayTime{
public static void main(String[] args){
try{
Socket socket = new Socket("stdtime.gov.hk",13);
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String daytime = br.readLine();
System.out.println("DayTime received:"+daytime);
socket.close();
}catch(IOException e){
System.out.println("ERROR:"+e);
}
}
}
b. ServerSocket類
ServerSocket類表示通訊雙方中的伺服器,它可以監聽用戶端發送的串連請求並進行處理。將伺服器所監聽的連接埠號碼傳遞給ServerSocket的構造方法,就可以建立一個ServerSocket對象。ServerSocket類的構造方法如下:
ServerSocket(int port);
ServerSocket(int port,int count);
其中,port表示連接埠號碼,count表示伺服器所能支援的最大串連數。例如:
ServerSocket serverSocket = new ServerSocket(5000);
這裡指定伺服器監聽的連接埠號碼是5000。當建立一個ServerSocket對象後,就可以調用accept()方法接受來自用戶端的請求。其格式為:
Socket socket = serverSocket.accept();
ServerSocket對象的accept()方法會使伺服器端的程式一直處於阻塞狀態,直到捕獲一個來自用戶端的請求,並返回一個Socket類的對象來處理與用戶端的通訊。
當需要結束監聽時,可以使用如下語句關閉這個ServerSocket對象:
serverSocket.close();
(6)資料報Socket編程
java.net包中提供了DatagramPacket和DatagramSocket類用來支援不需連線的資料報Socket通訊。DatagramSocket類用於在程式之間建立傳送資料報的通訊串連,DatagramPacket類則用於儲存資料報等資訊。
a. DatagramSocket類:構造方法如下:
DatagramSocket();
DatagramSocket(int port);
DatagramSocket(int port,InetAddress localAddr);
其中,port表示連接埠號碼;localAddr表示本地地址。
DatagramSockt類構造方法會拋出非運行時異常SocketException,程式需要對此進行處理。
b. DatagramPacket類:
用資料報方式編寫Client/Server程式時,無論在用戶端還是伺服器,都首先需要建立一個DatagramSocket對象,用來接收或發送資料報,而DatagramPacket對象是資料報傳輸的載體。構造方法如下:
DatagramPacket(byte[] buf,int length);
DatagramPacket(byte[] buf,int length,InetAddress address,int port);
其中,位元組數組buf中存放欲發送或接收的資料報,length表示資料報的長度,address和port表示資料報發送的目的地和主機連接埠號碼。
在用戶端或伺服器端接收資料之前,應該採用DatagramPacket類的第一種構造方法建立一個DatagramPacket對象,然後調用DatagramSocket類的receive()方法等待資料報的到來。例如:
DatagramSocket socket = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(buf,256);
socket.receive();
在發送資料之前,需要使用DatagramPacekt類的第二種構造方法建立一個新的DatagramPacket對象,即要指明資料報發送的目的地址和連接埠號碼。發送資料報通過DatagramSocket類的send()方法實現。例如:
DatagramSocket socket = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(buf,length,address,port);
socket.send(packet);
Java學習筆記—第十二章 Java網路編程入門