Java(老白再次入門) - 網絡編程

本系列文章均爲尚硅谷資源!如有侵權,我將立即刪除!

Java基礎知識圖解

在這裏插入圖片描述

1.網絡編程概述

JavaInternet 上的語言,它從語言級上提供了對網絡應用程序的支持,程序員能夠很容易開發常見的網絡應用程序。
Java提供的網絡類庫,可以實現無痛的網絡連接,聯網的底層細節被隱藏在 Java 的本機安裝系統裏,由 JVM 進行控制。並且 Java 實現了一個跨平臺的網絡庫,程序員面對的是一個統一的網絡編程環境。

網絡基礎

計算機網絡:
把分佈在不同地理區域的計算機與專門的外部設備用通信線路互連成一個規模大、功能強的網絡系統,從而使衆多的計算機可以方便地互相傳遞信息、共享硬件、軟件、數據信息等資源。
網絡編程的目的:

  • 直接或間接地通過網絡協議與其它計算機實現數據交換,進行通訊。

網絡編程中有兩個主要的問題:

  • 如何準確地定位網絡上一臺或多臺主機;定位主機上的特定的應用
  • 找到主機後如何可靠高效地進行數據傳輸

2.網絡通信要素概述

IP和端口號
網絡通信協議

如何實現網絡中的主機互相通信

通信雙方地址

  • IP
  • 端口號

一定的規則(即:網絡通信協議。有兩套參考模型)

  • OSI參考模型:模型過於理想化,未能在因特網上進行廣泛推廣
  • TCP/IP參考模型(或TCP/IP協議):事實上的國際標準。
網絡通信協議

在這裏插入圖片描述
在這裏插入圖片描述

3.通信要素1:IP和端口號

IP 地址:InetAddress

唯一的標識 Internet 上的計算機(通信實體)
本地迴環地址(hostAddress):127.0.0.1 主機名(hostName):localhost
IP地址分類方式1:IPV4IPV6

  • IPV44個字節組成,40-255。大概42億,30億都在北美,亞洲4億。2011年初已經用盡。以點分十進制表示,如192.168.0.1
  • IPV6128位(16個字節),寫成8個無符號整數,每個整數用四個十六進制位表示,數之間用冒號(:)分開,如:3ffe:3201:1401:1280:c8ff:fe4d:db39:1984

IP地址分類方式2:公網地址(萬維網使用)私有地址(局域網使用)192.168.開頭的就是私有址址,範圍即爲192.168.0.0–192.168.255.255,專門爲組織機構內部使用
特點:不易記憶

端口號 標識正在計算機上運行的進程(程序)

不同的進程有不同的端口號
被規定爲一個 16 位的整數 0~65535
端口分類:

  • 公認端口0~1023。被預先定義的服務通信佔用(如:HTTP佔用端口 80,FTP佔用端口21,Telnet佔用端口23
  • 註冊端口1024~49151。分配給用戶進程或應用程序。(如:Tomcat佔用端口8080,MySQL佔用端口3306,Oracle佔用端口1521等)。
  • 動態/私有端口49152~65535。

端口號與IP地址的組合得出一個網絡套接字:Socket。

在這裏插入圖片描述

InetAddress類

Internet上的主機有兩種方式表示地址:

  • 域名(hostName):www.atguigu.com
  • IP 地址(hostAddress):202.108.35.210

InetAddress類主要表示IP地址,兩個子類:Inet4Address、Inet6Address。
InetAddress 類 對 象 含 有 一 個 Internet 主 機 地 址 的 域 名 和 IP 地 址 :www.atguigu.com202.108.35.210
域名容易記憶,當在連接網絡時輸入一個主機的域名後,域名服務器**(DNS)**負責將域名轉化成IP地址,這樣才能和主機建立連接。 -------域名解析

在這裏插入圖片描述
InetAddress類沒有提供公共的構造器,而是提供瞭如下幾個靜態方法來獲取InetAddress實例

  • public static InetAddress getLocalHost()
  • public static InetAddress getByName(String host)

InetAddress提供瞭如下幾個常用的方法

  • public String getHostAddress():返回 IP 地址字符串(以文本表現形式)。
  • public String getHostName():獲取此 IP 地址的主機名
  • public boolean isReachable(int timeout):測試是否可以達到該地址
InetAddress address_1 = InetAddress.getByName("www.baidu.com");

System.out.println(address_1);
//獲取 InetAddress 對象所含的域名
System.out.println(address_1.getHostName());
//獲取InetAddress 對象所含的IP地址
System.out.println(address_1.getHostAddress());

//獲取本機的域名和IP地址
InetAddress address_1 = InetAddress.getByName("www.baidu.com");
System.out.println(address_2);


4.通信要素2:網絡協議

網絡通信協議
計算機網絡中實現通信必須有一些約定,即通信協議,對速率、傳輸代碼、代碼結構、傳輸控制步驟、出錯控制等制定標準。
問題:網絡協議太複雜
計算機網絡通信涉及內容很多,比如指定源地址和目標地址,加密解密,壓縮解壓縮,差錯控制,流量控制,路由控制,如何實現如此複雜的網絡協議呢?
通信協議分層的思想
在制定協議時,把複雜成份分解成一些簡單的成份,再將它們複合起來。最常用的複合方式是層次方式,即同層間可以通信、上一層可以調用下一層,而與再下一層不發生關係。各層互不影響,利於系統的開發和擴展。

TCP/IP協議簇

傳輸層協議中有兩個非常重要的協議:

  • 傳輸控制協議TCP(Transmission Control Protocol)
  • 用戶數據報協議UDP(User Datagram Protocol)。

**TCP/IP 以其兩個主要協議:傳輸控制協議(TCP)和網絡互聯協議(IP)**而得名,實際上是一組協議,包括多個具有不同功能且互爲關聯的協議。

  • IP(Internet Protocol)協議是網絡層的主要協議,支持網間互連的數據通信。
  • TCP/IP協議模型從更實用的角度出發,形成了高效的四層體系結構,即物理鏈路層、IP層、傳輸層和應用層。

TCP 和 UDP

TCP協議:

  • 使用TCP協議前,須先建立TCP連接,形成傳輸數據通道
  • 傳輸前,採用“三次握手”方式,點對點通信,是可靠的
  • TCP協議進行通信的兩個應用進程:客戶端、服務端。
  • 在連接中可進行大數據量的傳輸
  • 傳輸完畢,需釋放已建立的連接,效率低

UDP協議:

  • 將數據、源、目的封裝成數據包,不需要建立連接
  • 每個數據報的大小限制在64K
  • 發送不管對方是否準備好,接收方收到也不確認,故是不可靠的
  • 可以廣播發送
  • 發送數據結束時無需釋放資源,開銷小,速度快

在這裏插入圖片描述
在這裏插入圖片描述

Socket

利用套接字(Socket)開發網絡應用程序早已被廣泛的採用,以至於成爲事實上的標準。
網絡上具有唯一標識的IP地址和端口號組合在一起才能構成唯一能識別的標識符套接字。
通信的兩端都要有Socket,是兩臺機器間通信的端點。
網絡通信其實就是Socket間的通信。
Socket允許程序把網絡連接當成一個流,數據在兩個Socket間通過IO傳輸。
一般主動發起通信的應用程序屬客戶端,等待通信請求的爲服務端
Socket分類:

  • 流套接字(stream socket):使用TCP提供可依賴的字節流服務
  • 數據報套接字(datagram socket):使用UDP提供“盡力而爲”的數據報服務

Socket類的常用構造器:

  • **public Socket(InetAddress address,int port)**創建一個流套接字並將其連接到指定 IP 地址的指定端口號。
  • **public Socket(String host,int port)**創建一個流套接字並將其連接到指定主機上的指定端口號。

Socket類的常用方法:

  • public InputStream getInputStream() 返回此套接字的輸入流。可以用於接收網絡消息
  • public OutputStream getOutputStream() 返回此套接字的輸出流。可以用於發送網絡消息
  • public InetAddress getInetAddress() 此套接字連接到的遠程 IP 地址;如果套接字是未連接的,則返回 null。
  • public InetAddress getLocalAddress() 獲取套接字綁定的本地地址。 即本端的IP地址
  • public int getPort() 此套接字連接到的遠程端口號;如果尚未連接套接字,則返回 0。
  • public int getLocalPort() 返回此套接字綁定到的本地端口。 如果尚未綁定套接字,則返回 -1。即本端的端口號。
  • public void close() 關閉此套接字。套接字被關閉後,便不可在以後的網絡連接中使用(即無法重新連接或重新綁定)。需要創建新的套接字對象。 關閉此套接字也將會關閉該套接字的 InputStreamOutputStream
  • public void shutdownInput() 如果在套接字上調用 shutd ownInput() 後從套接字輸入流讀取內容,則流將返回 EOF(文件結束符)。 即不能在從此套接字的輸入流中接收任何數據。
  • public void shutdownOutput() 禁用此套接字的輸出流。對於 TCP 套接字,任何以前寫入的數據都將被髮送,並且後跟 TCP 的正常連接終止序列。 如果在套接字上調用 shutdownOutput() 後寫入套接字輸出流,則該流將拋出 IOException。 即不能通過此套接字的輸出流發送任何數據。

5.TCP網絡編程

基於Socket的TCP編程

Java語言的基於套接字編程分爲服務端編程和客戶端編程,其通信模型如圖所示:
在這裏插入圖片描述

客戶端Socket的工作過程包含以下四個基本的步驟:
  • 創建 Socket:根據指定服務端的 IP 地址或端口號構造 Socket 類對象。若服務器端響應,則建立客戶端到服務器的通信線路。若連接失敗,會出現異常。
  • 打開連接到 Socket 的輸入/出流: 使用 getInputStream()方法獲得輸入流,使用getOutputStream()方法獲得輸出流,進行數據傳輸
  • 按照一定的協議對 Socket 進行讀/寫操作:通過輸入流讀取服務器放入線路的信息(但不能讀取自己放入線路的信息),通過輸出流將信息寫入線程。
  • 關閉 Socket:斷開客戶端到服務器的連接,釋放線路

客戶端創建Socket對象

客戶端程序可以使用Socket類創建對象,創建的同時會自動向服務器方發起連接。Socket的構造器是:

  • Socket(String host,int port)throws UnknownHostException,IOException:向服務器(域名是host。端口號爲port)發起TCP連接,若成功,則創建Socket對象,否則拋出異常
  • Socket(InetAddress address,int port)throws IOException:根據InetAddress對象所表示的IP地址以及端口號port發起連接。

客戶端建立socketAtClient對象的過程就是向服務器發出套接字連接請求

Socket s = new Socket(192.168.40.165,9999);
OutputStream out = s.getOutputStream();
out.write(" hello".getBytes());
s.close();
服務器程序的工作過程包含以下四個基本的步驟:
  • 調用 ServerSocket(int port) :創建一個服務器端套接字,並綁定到指定端口上。用於監聽客戶端的請求。
  • 調用 accept():監聽連接請求,如果客戶端請求連接,則接受連接,返回通信套接字對象。
  • 調用 該Socket類對象的 getOutputStream() 和 getInputStream ():獲取輸出流和輸入流,開始網絡數據的發送和接收。
  • 關閉ServerSocket和Socket對象:客戶端訪問結束,關閉通信套接字。

服務器建立 ServerSocket 對象

ServerSocket 對象負責等待客戶端請求建立套接字連接,類似郵局某個窗口中的業務員。也就是說,服務器必須事先建立一個等待客戶請求建立套接字連接的ServerSocket對象。
所謂“接收”客戶的套接字請求,就是**accept()**方法會返回一個 Socket 對象

ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept ();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int num = in.read(buf);
String str = new String(buf,0,num);
System.out.println(s.getInetAddress().toString()+:+str);
s.close();
ss.close()

在這裏插入圖片描述

客戶端—服務端

客戶端:

  • 自定義
  • 瀏覽器

服務端:

  • 自定義
  • Tomcat服務器

6.UDP網絡編程

UDP網絡通信

DatagramSocketDatagramPacket 實現了基於 UDP 協議網絡程序。
UDP數據報通過數據報套接字 DatagramSocket 發送和接收,系統不保證
UDP數據報一定能夠安全送到目的地,也不能確定什麼時候可以抵達。
DatagramPacket 對象封裝了UDP數據報,在數據報中包含了發送端的IP地址和端口號以及接收端的IP地址和端口號。
UDP協議中每個數據報都給出了完整的地址信息,因此無須建立發送方和接收方的連接。如同發快遞包裹一樣。

DatagramSocket 類的常用方法

  • public DatagramSocket(int port)創建數據報套接字並將其綁定到本地主機上的指定端口。套接字將被綁定到通配符地址,IP 地址由內核來選擇。
  • public DatagramSocket(int port,InetAddress laddr)創建數據報套接字,將其綁定到指定的本地地址。本地端口必須在 0 到 65535 之間(包括兩者)。如果 IP 地址爲 0.0.0.0,套接字將被綁定到通配符地址,IP 地址由內核選擇。
  • public void close()關閉此數據報套接字。
  • public void send(DatagramPacket p)從此套接字發送數據報包。DatagramPacket 包含的信息指示:將要發送的數據、其長度、遠程主機的 IP 地址和遠程主機的端口號。
  • public void receive(DatagramPacket p)從此套接字接收數據報包。當方法返回時,DatagramPacket的緩衝區填充了接收的數據。數據報包也包含發送方的 IP 地址和發送方機器上的端口號。 此方法在接收到數據報前一直阻塞。數據報包對象的 length 字段包含所接收信息的長度。如果信息比包的長度長,該信息將被截短。
  • public InetAddress getLocalAddress()獲取套接字綁定的本地地址。
  • public int getLocalPort()返回此套接字綁定的本地主機上的端口號。
  • public InetAddress getInetAddress()返回此套接字連接的地址。如果套接字未連接,則返回 null。
  • public int getPort()返回此套接字的端口。如果套接字未連接,則返回 -1。

DatagramPacket類的常用方法

  • public DatagramPacket(byte[] buf,int length)構造 DatagramPacket,用來接收長度爲 length 的數據包。 length 參數必須小於等於 buf.length。
  • public DatagramPacket(byte[] buf,int length,InetAddress address,int port)構造數據報包,用來將長度爲 length 的包發送到指定主機上的指定端口號。length參數必須小於等於 buf.length。
  • public InetAddress getAddress()返回某臺機器的 IP 地址,此數據報將要發往該機器或者是從該機器接收到的。
  • public int getPort()返回某臺遠程主機的端口號,此數據報將要發往該主機或者是從該主機接收到的。
  • public byte[] getData() 返回數據緩衝區。接收到的或將要發送的數據從緩衝區中的偏移量 offset 處開始,持續 length 長度。
  • public int getLength() 返回將要發送或接收到的數據的長度。
UDP網絡通信

流 程:

  1. DatagramSocketDatagramPacket
  2. 建立發送端,接收端
  3. 建立數據包
  4. 調用Socket的發送、接收方法
  5. 關閉Socket

發送端與接收端是兩個獨立的運行程序

發送端
DatagramSocket ds = null;
try {
	ds = new DatagramSocket();
	byte[] by = "hello,atguigu.com".getBytes();
	DatagramPacket dp = new DatagramPacket(by, 0, by.length, 
	InetAddress.getByName("127.0.0.1"), 10000);
	ds.send(dp);
} catch (Exception e) {
	e.printStackTrace();
	} finally {
		if (ds != null)
			ds.close();
}
接收端

在接收端,要指定監聽的端口。

DatagramSocket ds = null;
try {
	ds = new DatagramSocket(10000);
	byte[] by = new byte[1024];
	DatagramPacket dp = new DatagramPacket(by, by.length);
	ds.receive(dp);
	String str = new String(dp.getData(), 0, dp.getLength());
	System.out.println(str + "--" + dp.getAddress());
} catch (Exception e) {
	e.printStackTrace();
	} finally {
		if (ds != null)
			ds.close();
}

7.URL編程

URL類

URL(Uniform Resource Locator):統一資源定位符,它表示 Internet 上某一資源的地址。
它是一種具體的URI,即URL可以用來標識一個資源,而且還指明瞭如何locate這個資源。
通過 URL 我們可以訪問 Internet 上的各種網絡資源,比如最常見的 www,ftp 站點。瀏覽器通過解析給定的 URL 可以在網絡上查找相應的文件或其他資源。
URL的基本結構由5部分組成:
<傳輸協議>://<主機名>:<端口號>/<文件名>#片段名?參數列表

  • 例如:
    http://192.168.1.100:8080/helloworld/index.jsp#a?username=shkstart&password=123
  • #片段名:即錨點,例如看小說,直接定位到章節
  • 參數列表格式:參數名=參數值**&**參數名=參數值…

URL類構造器

爲了表示URLjava.net 中實現了類 URL。我們可以通過下面的構造器來初始化一個 URL 對象:

  • public URL (String spec):通過一個表示URL地址的字符串可以構造一個URL對象。例 如:URL url = new URL (“http://www. atguigu.com/”);
  • public URL(URL context, String spec):通過基 URL 和相對 URL 構造一個 URL 對象。 例如:URL downloadUrl = new URL(url, “download.html")
  • public URL(String protocol, String host, String file); 例如:new URL(“http”, “www.atguigu.com”, “download.html");
  • public URL(String protocol, String host, int port, String file); 例如: URL gamelan = new URL(“http”, “www.atguigu.com”, 80, “download.html");

URL類的構造器都聲明拋出非運行時異常,必須要對這一異常進行處理,通常是用 try-catch 語句進行捕獲。

URL類常用方法

一個URL對象生成後,其屬性是不能被改變的,但可以通過它給定的方法來獲取這些屬性:

  • public String getProtocol( ) 獲取該URL的協議名
  • public String getHost( ) 獲取該URL的主機名
  • public String getPort( ) 獲取該URL的端口號
  • public String getPath( ) 獲取該URL的文件路徑
  • public String getFile( ) 獲取該URL的文件名
  • public String getQuery( ) 獲取該URL的查詢名
URL url = new URL("http://localhost:8080/examples/myTest.txt");
System.out.println("getProtocol() :"+url.getProtocol());
System.out.println("getHost() :"+url.getHost());
System.out.println("getPort() :"+url.getPort());
System.out.println("getPath() :"+url.getPath());
System.out.println("getFile() :"+url.getFile());
System.out.println("getQuery() :"+url.getQuery());

針對HTTP協議的URLConnection類

URL的方法 openStream():能從網絡上讀取數據
若希望輸出數據,例如向服務器端的 CGI (公共網關接口-Common Gateway Interface-的簡稱,是用戶瀏覽器和服務器端的應用程序進行連接的接口)程序發送一些數據,則必須先與URL建立連接,然後才能對其進行讀寫,此時需要使用URLConnection 。
URLConnection:表示到URL所引用的遠程對象的連接。當與一個URL建立連接時,首先要在一個 URL 對象上通過方法 openConnection() 生成對應的 URLConnection對象。如果連接過程失敗,將產生IOException.

  • URL netchinaren = new URL (“http://www.atguigu.com/index.shtml”);
  • URLConnectonn u = netchinaren.openConnection( );

通過URLConnection對象獲取的輸入流和輸出流,即可以與現有的CGI程序進行交互。

  • public Object getContent( ) throws IOException
  • public intgetContentLength( )
  • public String getContentType( )
  • public longgetDate( ) public long getLastModified( )
  • public InputStream getInputStream( )throws IOException
  • public OutputSteram getOutputStream( )throws IOException
URI、URL和URN的區別

URI,是uniform resource identifier,統一資源標識符,用來唯一的標識一個資源。而URL是uniform resource locator,統一資源定位符,它是一種具體的URI,即URL可以用來標識一個資源,而且還指明瞭如何locate這個資源。而URN,uniform resource name,統一資源命名,是通過名字來標識資源,比如mailto:[email protected]。也就是說,URI是以一種抽象的,高層次概念定義統一資源標識,而URL和URN則是具體的資源標識的方式。URL和URN都是一種URI。
在這裏插入圖片描述
在Java的URI中,一個URI實例可以代表絕對的,也可以是相對的,只要它符合URI的語法規則。而URL類則不僅符合語義,還包含了定位該資源的信息,因此它不能是相對的。

小 結

😃 位於網絡中的計算機具有唯一的IP地址,這樣不同的主機可以互相區分。
😃 客戶端-服務器是一種最常見的網絡應用程序模型。服務器是一個爲其客戶端提供某種特定服務的硬件或軟件。客戶機是一個用戶應用程序,用於訪問某臺服務器提供的服務。端口號是對一個服務的訪問場所,它用於區分同一物理計算機上的多個服務。套接字用於連接客戶端和服務器,客戶端和服務器之間的每個通信會話使用一個不同的套接字。TCP協議用於實現面向連接的會話。
😃 Java 中有關網絡方面的功能都定義在 java.net 程序包中。JavaInetAddress 對象表示 IP
地址,該對象裏有兩個字段:主機名(String) 和 IP 地址(int)。
😃 類 SocketServerSocket 實現了基於TCP協議的客戶端-服務器程序。Socket是客戶端和服務器之間的一個連接,連接創建的細節被隱藏了。這個連接提供了一個安全的數據傳輸通道,這是因爲 TCP 協議可以解決數據在傳送過程中的丟失、損壞、重複、亂序以及網絡擁擠等問題,它保證數據可靠的傳送。
😃 類 URLURLConnection 提供了最高級網絡應用。URL 的網絡資源的位置來同一表示Internet 上各種網絡資源。通過URL對象可以創建當前應用程序和 URL 表示的網絡資源之間的連接,這樣當前程序就可以讀取網絡資源數據,或者把自己的數據傳送到網絡上去。

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