第1關:URL類與InetAddress類
任務描述
本關任務:了解網絡編程基礎知識。
相關知識
為了完成本關任務,你需要掌握:1.URL;2.InetAddress。
URL
統一資源定位符(Uniform Resource Locator,縮寫為URL)是對可以從互聯網上得到的資源的位置和訪問方法的一種簡潔的表示,是互聯網上標準資源的地址。 互聯網上的每個文件都有一個唯一的URL,它包含的信息指出文件的位置以及瀏覽器應該怎么處理它。
URL可以分為如下幾個部分:
protocol://host:port/path?query#fragment
HTTP 協議的 URL 實例如下:
http://www.runoob.com/index.html?language=cn#javase
- 協議為(protocol):
http
- 主機為(host:port):
www.runoob.com
- 端口號為(port):
80
,以上URL實例并未指定端口,因為 HTTP 協議默認的端口號為80
- 文件路徑為(path):
/index.html
- 請求參數(query):
language=cn
- 定位位置(fragment):
javase
,定位到網頁中id
屬性為javase
的HTML
元素位置。
URL對象
java.net
包中的 URL
類是對統一資源定位符的抽象,使用 URL
創建對象的應用程序稱作客戶端程序。一個URL
對象通常包含最基本的三部分信息:協議、地址和資源。
URL
對象定義public URL(String spec) throws MalformedURLException
public URL(String protocol, String host, String file) throws MalformedURLException
- 讀取
URL
中的資源:URL
對象調用InputStream openStream()
方法返回一個輸入流,該輸入流指向URL
對象所包含的資源。通過該輸入流可以將服務器上的資源信息讀入到客戶端。
InetAddress 類
InetAddress
類是Java對IP
地址的封裝,在java.net
中有許多類都使用到了InetAddress
類,包括:ServerSocket
,Socket
,DatagramSocket
等等。 InetAddress
對域名進行解析是使用本地機器配置或者網絡命名服務(如域名系統(Domain Name System,DNS
)和網絡信息服務(Network Information Service,NIS
))來實現。對于DNS
來說,本地需要向DNS
服務器發送查詢的請求,然后服務器根據一系列的操作,返回對應的IP
地址。 為了提高效率,通常本地會緩存一些主機名與IP
地址的映射,這樣訪問相同的地址,就不需要重復發送DNS
請求了。在java.net.InetAddress
類同樣采用了這種策略。默認情況下,會緩存一段有限時間的映射,對于主機名解析不成功的結果,會緩存非常短的時間(10秒)來提高性能。
該類沒有構造器,可以通過它的兩個靜態方法來獲取InetAddress
的實例。
getByName(String s)
:獲取InetAddress
對象
- 用域名作為
getByName()
和getAllByName()
方法的參數得到的InetAddress
對象,該對象會得到這個域名,當調用getHostName()
時,就無需再訪問DNS
服務器,而是直接將這個域名返回。 - 用IP地址作為
getByName()
,getAllByName()
,getByAddress()
方法的參數,創建InetAddress
對象時,并不需要訪問DNS
服務器。因此,通過DNS
服務器查找域名的工作就由getHostName()
方法來完成。如果IP
地址不存在或DNS
服務器不允許進行IP
地址和域名映射,就返回這個IP
地址。 - 用主機名作為參數創建InetAddress對象。
- 靜態方法
getLocalHost()
獲取本機的InetAddress
。如果獲取不到(可能是安全問題),就會返回地址:127.0.0.1
和 主機名:localhost
。
getByAddress(byte[] addr)
:根據源IP
地址來獲取InetAddress
對象。
編程要求
根據提示,使用URL
類和InetAddress
類編程,在右側編輯器 Begin-End
補充代碼。
- 使用
java.net
的URL
類獲取URL
的各個部分參數 - 使用
InetAddress
類的getAllByName()
方法,輸出百度主機的所有地址
測試說明
平臺會對你編寫的代碼進行測試:
測試輸入:
預期輸出:
協議為:http
主機名:www.runoob.com
路徑:/index.html
端口:-1
請求參數:language=cn
www.baidu.com/180.101.50.188
www.baidu.com/180.101.49.242
注明:百度主機輸出結果的順序不一致時,可以多評測幾次。
代碼實現
package step1;import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;public class Step1Test
{public static void main(String[] args){// URL地址:http://www.runoob.com/index.html?language=cn#javase// 1. 要求輸出:協議、主機名、路徑、端口、請求參數// ********** Begin **********try{URL url = new URL("http://www.runoob.com/index.html?language=cn#javase");System.out.println("協議為:" + url.getProtocol());System.out.println("主機名:" + url.getHost());System.out.println("路徑:" + url.getPath());System.out.println("端口:" + url.getPort());System.out.println("請求參數:" + url.getQuery());}catch (MalformedURLException e){e.printStackTrace();}// 2. 輸出百度的所有主機地址// ********** End **********try{InetAddress[] addresses = InetAddress.getAllByName("www.baidu.com");// for (InetAddress address : addresses)// {// System.out.println("www.baidu.com/" + address.getHostAddress());// }System.out.println("www.baidu.com/" + addresses[0].getHostAddress());System.out.println("www.baidu.com/" + addresses[1].getHostAddress());}catch (UnknownHostException e){e.printStackTrace();}}
}
第2關:TCP Socket通信
任務描述
本關任務:編寫程序實現基于TCP/IP協議的Socket通信。
相關知識
為了完成本關任務,你需要掌握:1.TCP/IP協議,2.Socket套接字,3.基于TCP/IP協議的Socket通信。
OSI參考模型和TCP/IP模型
計算機網絡市場剛剛興起時,許多計算機生產廠商都積極推出自己公司獨創的網絡。由于這些網絡都不互通,導致使用某種網絡的用戶如果在后續擴展網絡時必須繼續使用原計算機廠商的設備。這樣使得市場上各自保護現象很嚴重。基于上述原因,國際標準化組織制定了一套標準,只要大家都遵循這套標準,那么各自的產品就可以相互兼容,這套標準就叫OSI參考模型。正所謂“沒有規矩不成方圓”。 OSI參考模型分為7層,分別是物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。分層有助于把網絡操作分成不太復雜的單元,分工合作,責任明確。
TCP/IP模型嚴格來說是一個四層的體系結構。應用層、傳輸層、網絡層和數據鏈路層都包含其中。雖然它有四層網絡模型層數,只是因為在TCP/IP模型中TCP模型和IP模型最具代表性,所以被稱為TCP/IP模型。TCP/IP模型具有數據的時新性、具有數據的時新性和傳輸技術的先進易用性。
TCP/IP協議
從字面意義上講,有人可能會認為 TCP/IP 是指 TCP 和 IP 兩種協議。實際生活當中有時也確實就是指這兩種協議。然而在很多情況下,它只是利用 IP 進行通信時所必須用到的協議群的統稱。具體來說,IP 或 ICMP、TCP 或 UDP、TELNET 或 FTP、以及 HTTP 等都屬于 TCP/IP 協議。它們與 TCP 或 IP 的關系緊密,是互聯網必不可少的組成部分。
Socket套接字
我們可以把所有渴望建立連接的對象都理解為套接字。要想建立網絡連接,就像插頭與插座套接在一起,而“字”則代表了可交互的有序指令串。Socket的引入就是為了解決不同計算機之間進程間相互通信的問題。
IP層的IP地址可以唯一標識Internet上的計算機,而TCP層協議和端口號可以唯一標識計算機上運行的一個進程,這樣我們可以利用“IP地址+協議+端口號”來唯一標識網絡中的一個進程。IP地址與端口號的組合可以得出一個Socket即網絡套接字。Socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層復雜的操作,抽象為幾個簡單的接口供應用層調用,以實現進程在網絡中的通信。能夠唯一標識網絡中的進程后,就可以利用Socket進行通信了。
Socket通信模型
具體地,Socket通信的過程,它通常分為三個步驟,分別是:服務器監聽,客戶端請求,連接確認。在 Java 語言中,需要使用 java.net 包中的ServerSocket類和Socket類來實現。
編程要求
請編寫程序實現基于TCP/IP協議的Socket通信過程。 服務器端程序平臺已經編寫完畢。需要你根據提示,在右側編輯器補充客戶端代碼。
- 服務器端開放: IP地址:
127.0.0.1
端口號:8889
- 客戶端發送數據:
Hello Server!
測試說明
服務器端代碼:
public class Server
{public static void main(String[] args) {try {ServerSocket ss = new ServerSocket(8889);System.out.println("啟動服務器....");Socket s = ss.accept();BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));//讀取客戶端發送來的消息String mess = br.readLine();System.out.println("客戶端:" + mess);ss.close();} catch (IOException e) {e.printStackTrace();}}
}
平臺會對你編寫的代碼進行測試:
測試輸入:
啟動服務器…
客戶端:測試客戶端與服務器通信:Hello Server!
開始你的任務吧,祝你成功!
代碼實現
package step2;import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;/*** 描述:描述:第2關:TCP Socket通信** @author 為一道彩虹*/
public class Client
{public static void main(String[] args){try {// 連接到IP地址為127.0.0.1,端口號為8889的服務器Socket socket = new Socket("127.0.0.1", 8889);// 獲取socket的輸出流OutputStream outputStream = socket.getOutputStream();// 使用PrintWriter包裝輸出流,方便發送字符串PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true);// 發送數據到服務器writer.println("測試客戶端與服務器通信:Hello Server!");// 關閉連接socket.close();}catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
第3關:UDP Socket通信
任務描述
本關任務:編寫程序實現基于UDP協議的Socket通信。
相關知識
為了完成本關任務,你需要掌握:1.UDP協議,2.Socket套接字,3.基于UDP協議的Socket通信。
UDP協議
基于UDP的通信和基于TCP的通信不同,基于UDP的信息傳遞更快,但不提供可靠性保證。即數據在傳輸時,用戶無法知道數據能否正確到達目的地主機,也不能確定數據到達目的地的順序是否和發送的順序相同。UDP通信比作郵遞信件。
基于UDP通信的基本模式:
- 將數據打包,稱為數據包,然后將數據包發往目的地。
- 接收別人發來的數據包,然后查看數據包中的內容。
Socket套接字
我們可以把所有渴望建立連接的對象都理解為套接字。要想建立網絡連接,就像插頭與插座套接在一起,而“字”則代表了可交互的有序指令串。Socket的引入就是為了解決不同計算機之間進程間相互通信的問題。
IP層的IP地址可以唯一標識Internet上的計算機,而TCP層協議和端口號可以唯一標識計算機上運行的一個進程,這樣我們可以利用“IP地址+協議+端口號”來唯一標識網絡中的一個進程。IP地址與端口號的組合可以得出一個Socket即網絡套接字。Socket是在應用層和傳輸層之間的一個抽象層,它把TCP/IP層復雜的操作,抽象為幾個簡單的接口供應用層調用,以實現進程在網絡中的通信。能夠唯一標識網絡中的進程后,就可以利用Socket進行通信了。
UDP Socket通信模型
- 用
DatagramPacket
類將數據打包,有兩個構造方法:
public DatagramPacket(byte[] data, int length, InetAddress address, int port)
;public DatagramPacket(byte[] data, int offset, int length, InetAddress address, int port)
;
- 用
DatagramSocket
類的不帶參數的構造方法DatagramSocket()
創建一個對象,該對象負責發送數據包。
DatagramSocket mail_out = new DatagramSocket();
Mail_out.send(data_pack);
- 用
DatagramSocket
類的另一個構造方法DatagramSocket(int port)
創建一個對象,其中的參數必須和待接收數據包的發送端口號相同。
DatagramSocket mail_in = new DatagramSocket(5666);
- 然后對象
mail_in
使用方法receive(DatagramPacket pack)
接收數據包。必須預備一個數據包以便接收數據包。這時需要使用DatagramPacket
類的另外一個構造方法DatagramPacket(byte[] data, int length)
創建一個數據包。
byte[] data = new byte[100];
int length = 90;
DatagramPacket pack = new DatagramPacket(data, length);
mail_in.receive(pack);
編程要求
請編寫程序實現基于UDP協議的Socket通信過程。 客戶端程序平臺已經編寫完畢。需要你根據提示,在右側編輯器補充服務器端代碼。 服務器端開放:
IP地址:127.0.0.1
或者localhost
端口號:12345
用于接收從客戶端發送過來的數據:
用戶名:admin;密碼:123
測試說明
客戶端代碼:
public class UDPClient
{public static void main(String[] args) throws IOException {/** 向服務器端發送數據*/// 1.定義服務器的地址、端口號、數據InetAddress address = InetAddress.getByName("localhost");int port = 12345;byte[] data = "用戶名:admin;密碼:123".getBytes();// 2.創建數據報,包含發送的數據信息DatagramPacket packet = new DatagramPacket(data, data.length, address, port);// 3.創建DatagramSocket對象DatagramSocket socket = new DatagramSocket();// 4.向服務器端發送數據報socket.send(packet);// 5.關閉資源socket.close();}
}
平臺會對你編寫的代碼進行測試:
測試輸入:
預期輸出:
****服務器端已經啟動,等待客戶端發送數據
我是服務器,客戶端說:用戶名:admin;密碼:123
開始你的任務吧,祝你成功!
代碼實現
package step3;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;public class UDPServer
{public static void main(String[] args) throws IOException{/** 接收客戶端發送的數據*/// 1.創建服務器端DatagramSocket,指定端口DatagramSocket socket = new DatagramSocket(12345);// 2.創建數據報,用于接收客戶端發送的數據// 創建字節數組,指定接收的數據包的大小1024byte[] receiveData = new byte[1024];DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);System.out.println("****服務器端已經啟動,等待客戶端發送數據");// 3.接收客戶端發送的數據socket.receive(receivePacket);// 4.讀取數據String receivedMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());System.out.println("我是服務器,客戶端說:" + receivedMessage);// 5.關閉資源socket.close();}
}
先贊后看,養成習慣!!!^ _ ^ ?? ?? ??
碼字不易,大家的支持就是我的堅持下去的動力。點贊后不要忘了關注我哦!