一、簡單的網絡知識
1、網絡模型:
①、OSI/RM(Open System Interconnection Reference Model開放式系統互連基本參考模型),是由ISO(International Standards Organization國際標準化組織)提出的網絡參考模型。
②、TCP/IP(Transmission Control Protocol/Internet Protocol 傳輸控制協議/因特網互聯協議)
③、兩種網絡模型的主要區別:
OSI/RM:7層模型。從低到高分別是:物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層、應用層
OSI/RM模型的網絡層同時支持面向連接和無連接的通信,但是傳輸層只支持面向連接的通信。
TCP/IP:4層模型。從低到高分別是:網絡接口層、網際層、傳輸層、應用層
TCP/IP模型的網絡層只提供無連接的服務,但是傳輸層上同時提供兩種通信模式。
④、網絡參考模型簡圖:
⑤、OSI/RM七層簡述:
物理層:主要定義物理設備標準,如網線的接口類型、光纖的接口類型、各種傳輸介質的傳輸速率等。主要作用是在物理媒體上傳輸原始的數據比特流(bit)。
數據鏈路層:主要將從物理層接收的數據進行MAC地址(網卡的地址)的封裝與解封裝。將數據分成一個個數據幀(frame),以數據幀爲單位傳輸。有應有答,遇錯重發。
網絡層:主要將從下層接收到的數據進行IP地址的封裝與解封裝。將數據分成一定長度的分組(數據包package),將分組穿過通信子網(即:下三層),從源端選擇路徑後傳到目的端。
傳輸層:爲會話層實體提供透明、可靠的數據傳輸服務,保證端到端的數據完整性;選擇網絡層的最適宜的服務;提供建立、維護和拆除傳輸連接功能。這一層傳輸的數據叫做段(segment)。
會話層:通過傳輸層(端口號:傳輸端口與接收端口)建立數據傳輸的通路。完成通信進程的邏輯名字(IP地址)與物理名字(MAC地址)間的對應;提供會話管理服務。
表示層:主要是進行對接收的數據進行解釋、加密與解密、壓縮與解壓縮等(也就是把計算機能夠識別的東西轉換成人能夠能識別的東西(如圖片、聲音等)。
應用層:主要是一些終端的應用。提供應用程序訪問OSI環境的方式。可以理解爲人們在電腦屏幕上能夠看到的東西。
2、網絡通信三要素:
①、IP地址(Internet Protocol Address):用來標識網絡上的一臺獨立的主機。
特點:
- 由32個二進制位,即4個字節組成。每兩個字節間用一個點(.)來分隔;例如:192.168.100.10
- IP地址通常用十進制數進行表示;
- IP地址可以分爲A、B、C、D、E五類。比較常用的是ABC三類。
- IP地址 = 網絡地址 + 主機地址
主機號:用於識別該網絡中的主機。
- l IP地址分爲IPV4、IPV6兩類。
IP地址分類以及範圍:
序號 |
地址分類 |
地址範圍 |
1 |
A類 |
1.0.0.1~129.255.255.254 |
2 |
B類 |
128.0.0.1~191.255.255.254 |
3 |
C類 |
192.0.0.1~223.255.255.254 |
4 |
D類 |
224.0.0.1~239.255.255.254 |
5 |
E類 |
240.0.0.1~255.255.255.254 |
缺點:
IP地址都是由數字組成,不太方便記憶。(但是可以將IP地址和域名對應起來,利用DNS解析就可以通過域名得到IP地址,只需要記住比較好記的域名就可以了)
特殊的IP地址:127.0.0.1(本地迴環地址、保留地址)可用於簡單的測試網卡是否故障。表示本機。
②、端口號:用於標識進程的邏輯地址。不同的進程都有不同的端口標識。
端口:要將數據發送到對方指定的應用程序上,爲了標識這些應用程序,所以給這些網絡應用程序都用數字進行標識。爲了方便稱呼這些數字,則將這些數字稱爲端口。(此端口是一個邏輯端口)
有效端口:範圍是0~65535,其中0~1024是系統使用或者保留端口。
③、傳輸協議:通訊的規則。例如:TCP、UDP協議
1、網絡通訊步驟:
確定對端IP地址→ 確定應用程序端口 → 確定通訊協議
總結:網絡通訊的過程其實就是一個(源端)不斷封裝數據包和(目的端)不斷拆數據包的過程。
簡單來說就是:發送方利用應用軟件將上層應用程序產生的數據前後加上相應的層標識不斷的往下層傳輸(封包過程),最終到達物理層通過看得見摸得着的物理層設備,例如:網線、光纖…等將數據包傳輸到數據接收方,然後接收方則通過完全相反的操作不斷的讀取和去除每一層的標識信息(拆包過程),最終將數據傳遞到最高層的指定的應用程序端口,並進行處理。
二、Java中網絡通信三要素的體現
1、IP地址:在Java中,使用java.net包中的InetAddress類來描述IP地址。
2、InetAddress類的繼承體系:
InetAddress
|--Inet4Address:用於表示IPV4
|--Inet6Address:用於表示IPV6
注意:InetAddress類沒有構造方法,無法通過new去實例化對象。但是可以通過InetAddress類提供的靜態方法來獲取該類的對象,用該類接收。同時可以通過InetAddress類提供的相關方法來獲取需要的信息,例如:IP地址、主機名等等。
InetAddress類的常用方法:
InetAddress getByName(String host):通過主機名獲取InetAddress對象。
InetAddress getLocalHost():獲取本機的InetAddress對象。
String getHostName():獲取主機名。
String getHostAddress():獲取主機的IP地址。
代碼示例:
import java.net.*;
class IPDemo
{
public static void main(String[] args) throws Exception
{
InetAddress i = InetAddress.getLocalHost();
System.out.println(i.toString()); //獲取當前主機的主機名和IP地址
System.out.println("ipaddress:"+i.getHostAddress()); //獲取本機ip地址。
System.out.println("hostname:"+i.getHostName()); //獲取本機主機名。
InetAddress ia = InetAddress.getByName("www.baidu.com");
System.out.println("ipaddress:"+ia.getHostAddress()); //獲取百度主機的ip地址。
System.out.println("hostname:"+ia.getHostName()); //獲取百度主機的主機名。
}
}
輸出結果:
hy-PC/172.16.128.143
ip address:172.16.128.143
hostname:hy-PC
ip address:119.75.218.77
hostname:www.baidu.com
由於可以通過InetAddress類的方法來獲取指定域名主機的IP地址,但是由於有些域名有多個IP地址,例如:百度、新浪、搜狐等服務器主機名可能對應多個IP地址,所以可以通過InetAddress類中的getAllByName()方法來獲取。
代碼示例:
import java.net.*;
class IPDemo
{
public static void main(String[] args) throws Exception
{
//可以通過InetAddress類中的靜態方法getAllByName()來獲取與指定主機名對應的多個IP地址信息。用一個InetAddress型數組接收。
InetAddress[] iaa = InetAddress.getAllByName("www.qq.com");
for(InetAddress ia : iaa)
{
System.out.println(ia.toString()); //通過高級for循環進行打印輸出。
}
}
}
輸出結果:
www.qq.com/101.226.129.158
4、端口:由於端口都是用數字進行標識,所以沒有必要將端口封裝成對象。
5、傳輸協議TCP和UDP
①、UDP:User Datagram Protocol用戶數據報協議
特點:
- 面向無連接:傳輸數據之前源端和目的端不需要建立連接。
- 每個數據報的大小都限制在64K(8個字節)以內。
- 面向報文的不可靠協議。(即:發送出去的數據不一定會接收得到)
- 傳輸速率快,效率高。
現實生活實例:郵局寄件、實時在線聊天、視頻會議…等。
②、TCP:Transmission Control Protocol傳輸控制協議
特點:
- 面向連接:傳輸數據之前需要建立連接。
- 在連接過程中進行大量數據傳輸。
- 通過“三次握手”的方式完成連接,是安全可靠協議。
- 傳輸速度慢,效率低。
現實生活實例:打電話、下載文件…等。
小知識點:TCP有6種標誌位:SYN(建立聯機)、ACK(確認)、PSH(傳送)、FIN(結束)、RST(重置)、URG(緊急)
Sequence number(順序號碼)Acknowledge number(確認號碼)
三次握手的過程:
第一次握手:建立連接時,客戶端發送SYN包(SYN=x)到服務器,並進入SYN_SEND狀態,等待服務器確認。
第二次握手:服務器收到SYN包,必須確認客戶端的SYN(ACK=x+1),同時自己也發送一個SYN包(SYN=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態。
第三次握手:客戶端接收到服務器的SYN+ACK包,向服務器發送確認包(ACK=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED狀態,完成三次握手。
三次握手完成之後,客戶端和服務器之間開始傳送數據。
三次握手過程圖解:
三次握手在現實生活中理解場景:
6、Socket的基本介紹:
① Socket編程:通常所說的網絡編程其實就是Socket編程。
②、什麼是socket?
Socket的字面意思是插槽、插座的意思。其實,Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。
Socket通常也稱作“套接字”,用於描述IP地址和端口。應用程序兩端通過“套接字”向網絡發出請求或者應答網絡請求。
③、Socket和ServerSocket類位於java.net包中。ServerSocket用於服務器端,Socket是建立網絡連接時使用的。
在連接成功時,應用程序兩端都會產生一個Socket實例,操作這個實例,完成所需的會話。對於一個網絡連接來說,套接字是平等的,並沒有差別,不因爲在服務器端或在客戶端而產生不同級別。
不管是Socket還是ServerSocket它們的工作都是通過SocketImpl類及其子類完成的。
④、Socket中的常用方法:
java.net.Socket類繼承與Object,有8個構造方法。其中三個使用最頻繁的方法:
void accept():用於獲取連接到服務端的客戶端對象,並且返回一個客戶端的Socket對象實例。該方法是一個阻塞式方法。
"阻塞"使程序運行暫時"停留",直到一個會話產生,然後程序繼續;通常"阻塞"是由循環產生的。
InputStream getInputStream():該方法獲得網絡連接輸入,同時返回一個IutputStream對象實例,。
OutputStream getOutputStream():該方法連接的另一端將得到輸入,同時返回一個OutputStream對象實例。
注意:其中getInputStream和getOutputStream方法均會產生一個IOException,它必須被捕獲,因爲它們返回的流對象,通常都會被另一個流對象使用。
⑤、C/S模型程序開發原理:
服務器Server:使用ServerSocket監聽指定的端口,端口可以隨意指定(由於1024以下的端口通常屬於保留端口,在一些操作系統中不可以隨意使用,所以建議使用大於1024的端口),等待客戶連接請求,客戶連接後,會話產生;在完成會話後,關閉連接。
客戶端Client:使用Socket對網絡上某一個服務器的某一個端口發出連接請求,一旦連接成功,打開會話。會話完成後,關閉Socket。客戶端不需要指定打開的端口,通常臨時的、動態的分配一個大於1024的端口。
三、TCP、UDP傳輸實現過程(步驟)
1、UDP傳輸:DatagramSocket/DatagramPacket
UDP傳輸實現步驟:
①、建立UDP傳輸的發送端和接收端。
②、提供數據,並將數據封裝到數據包中。
③、調用Socket服務的發送、接收功能,將數據包發出去或者接收回來。
④、關閉Socket服務。
/*
需求:通過UDP傳輸方式,將一段文字數據發送出去。
定義UDP發送端:
思路(實現步驟):
1、建立UDP的Socket服務。
2、提供數據,並將數據封裝到數據包中。
3、通過Socket服務的發送功能,將數據包發出去。
4、關閉資源。
*/
import java.net.*;
class UdpSend
{
public static void main(String[] args) throws Exception
{
//1、創建udp服務,通過DatagramSocket對象。
DatagramSocket ds = new DatagramSocket();
//2、確定數據,並封裝成數據包。
byte[] buf = "udp I am coming...".getBytes(); //將數據封裝成字節數組。
DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.88"),10000); //將指定長度的數據發送到指定IP地址主機的指定端口。
//3、通過socket服務,將已有的數據包發送出去。通過send方法。
ds.send(dp);
//4、關閉資源。
ds.close();
}
}
UDP接收端:
/*
需求:定義一個應用程序,用於接收udp協議傳輸的數據並處理的。
思路(實現步驟):
1、定義UDP的Socket服務。通常會監聽一個端口,其實就是給這個接收網絡應用程序定義數字標識。方便於明確哪些數據過來,該應用程序可以處理。(如果不指定監聽端口,系統會自動分配一個監聽端口)
2、定義一個數據包,因爲要存儲接收到的字節數據。因爲數據包對象中有更多功能可以提取字節數據中的不同數據信息。
3、通過Socket服務的receive方法將收到的數據存入已定義好的數據包中。
4、通過數據包對象的特有功能,將這些不同的數據取出。打印在控制檯上。
5、關閉資源。
*/
import java.io.*;
import java.net.*;
class UdpRece
{
public static void main(String[] args) throws Exception
{
//1、創建UDP的Socket服務。建立端點。
DatagramSocket ds = new DatagramSocket(10000);
//2、定義數據包。用於存儲數據。
byte[] buf = new byte[1024];
DatagramPacket dp = new DatagramPacket(buf,buf.length);
//3、通過Socket服務的receive方法,將收到的數據存入數據包中。
ds.receive(dp); //receive方法是一個“阻塞式”方法,相當於線程當中的wait方法。即當沒有數據發送過來的時候,就一致處於等待狀態。
//4、通過數據包的方法獲取其中的數據。
String ip = dp.getAddress().getHostAddress(); //獲取ip地址。
String data = new String(dp.getData(),0,dp.getLength()); //獲取數據。
int port = dp.getPort(); //獲取端口。
System.out.println(ip+"::"+data+"::"+port);
//5、關閉資源。
ds.close();
}
}
2、TCP傳輸:Socket/ServerSocket
TCP傳輸實現步驟:
①、建立TCP傳輸的客戶端(Socket)和服務端(ServerSocket)。
②、建立連接後,通過Socket中的IO流進行數據的傳輸。
③、關閉Socket服務。
TCP傳輸基本思路:
①、客戶端:
- 客戶端需要明確服務器的ip地址以及端口,這樣纔可以去試着建立連接,如果連接失敗,會出現異常。
- 連接成功,說明客戶端與服務端建立了通道,那麼通過IO流就可以進行數據的傳輸,而Socket對象已經提供了輸入流和輸出流對象,通過getInputStream(),getOutputStream()獲取即可。
- 與服務端通訊結束後,關閉Socket服務。
②、服務端:
- 服務端需要明確它要處理的數據是從哪個端口進入的。(監聽端口)
- 當有客戶端訪問時,要明確是哪個客戶端,可通過accept()獲取已連接的客戶端對象,並通過該對象與客戶端通過IO流進行數據傳輸。
- 當該客戶端訪問結束,關閉該客戶端服務。
③ 、TCP傳輸示例圖:
<span style="font-size:10px;">import java.io.*;
import java.net.*;
/*
客戶端:
通過查閱Socket對象,在該對象建立時就可以去連接指定主機。
因爲TCP是面向連接的,所以在建立Socket服務時,就要有服務端存在並連接成功。形成通路後,在該通道進行數據的傳輸。
需求:給服務端發送一個文本數據。
步驟:
1、創建Socket服務,並指定要連接的主機和端口。
*/
class TcpClient
{
public static void main(String[] args) throws Exception
{
//創建客戶端的Socket服務,指定目的主機和端口。
Socket s = new Socket("192.168.1.88",10003);
//爲了發送數據,應該獲取Socket流中的輸出流。
OutputStream out = s.getOutputStream();
out.write("tcp I am coming...".getBytes());
s.close();
}
}
/*
需求:定義端點接收數據,並打印在控制檯上。
服務端:
1、建立服務端的Socket服務,通過ServerSocekt();並監聽一個端口。
2、獲取連接過來的客戶端對象。通過ServerSocket的accept方法完成。沒有連接就會一直等,所以這個方法是一個阻塞式方法。
3、客戶端如果發過來數據,那麼服務端要使用對應的客戶端對象,並獲取到該客戶端對象的讀取流來讀取發過來的數據。並打印在控制檯。
4、關閉服務端。(可選)
*/
class TcpServer
{
public static void main(String[] args) throws Exception
{
//建立服務端的Socket服務,並監聽一個端口。
ServerSocket ss = new ServerSocket(10003);
//通過accept方法獲取連接過來的客戶端對象。
Socket s = ss.accept();
//獲取客戶端連接過來的主機IP地址。
String ip = s.getInetAddress().getHostAddress();
System.out.println(ip+"......connect");
//獲取客戶端發送過來的數據,那麼要使用客戶端對象的讀取流方法來讀取數據。
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(new String(buf,0,len));
s.close(); //關閉客戶端。
}
}
四、URL與URLConnection
1、 URL:(UniformResource Locator)統一資源定位符。
2、 URL類的常用方法:
URL(String spec):根據 String表示形式創建 URL對象。
URL(String protocol, String host, int port, Stringfile):根據指定 protocol、host、port號和 file創建 URL對象。
String getFile():獲取此 URL的文件名。
String getHost():獲取此 URL的主機名(如果適用)。
String getPath():獲取此 URL的路徑部分。
int getPort():獲取此 URL的端口號。當返回值爲-1的時候,表示使用http協議默認的端口號:80
String getProtocol():獲取此 URL的協議名稱。
String getQuery():獲取此 URL的查詢部分。(獲取web路徑之後的具體參數信息)
URLConnection openConnection():返回一個URLConnection
對象,它表示到URL
所引用的遠程對象的連接。
代碼示例:
import java.net.*;
class URLDemo
{
public static void main(String[] args) throws Exception
{
URL url = new URL("http://172.16.128.143:8080/myweb/demo.html?name=haha&age=30");
System.out.println("getProtoclo():"+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());
/*
intport = getPort();
if(port==-1)
port = 80;
*/
}
}
輸出結果:
getProtoclo() :http
getHost() :172.16.128.143
getPort() :8080
getPath() :/myweb/demo.html
getFile() :/myweb/demo.html?name=haha&age=30
getQuery() :name=haha&age=30
3、 URLConnection(該類封裝了訪問遠程網絡資源的一般方法)
①、作用:可以通過URLConnecton類對象與遠程服務器建立連接,並獲取遠程資源的一些屬性信息。
URLConnection
|-- HttpURLConnection:將http請求和應答在應用層使用Http協議解析,請求和應答消息頭不會顯示出來。而Socket是在傳輸層。
|-- JarURLConnection
代碼示例:
import java.net.*;
import java.io.*;
class URLConnectionDemo
{
public static void main(String[] args) throws Exception
{
URL url = new URL("http://172.16.128.143:8080/myweb/demo.html");
URLConnection conn = url.openConnection();
System.out.println(conn); //HttpURLConnection
InputStream in = conn.getInputStream();
byte[] buf = new byte[1024];
int len = in.read(buf);
System.out.println(newString(buf,0,len));
}
}
②、常用方法介紹:
int getContentLength():返回content-length
頭字段的值。
String getContentType():返回content-type
頭字段的值。
InputStream getInputStream():返回從此打開的連接讀取的輸入流。
longgetDate():返回date
頭字段的值。
代碼示例:
import java.net.*;
class URLConnectionDemo2
{
public static void main(String[] args) throws Exception
{
URL urlPath = new URL("http://www.sina.com.cn");
URLConnection conn = urlPath.openConnection(); //和遠程對象建立連接。
System.out.println("content-length:"+conn.getContentLength());
System.out.println("content-type:"+conn.getContentType());
System.out.println("data:"+conn.getDate());
}
}
輸出結果:
content-length:538061
content-type:text/html
data:1403515169000
五、“域名解析”介紹
1、DNS:Domain Name System域名系統。是域名和IP地址的一種映射關係。
2、DNS的作用:可以將域名解析成IP地址,方便記憶。(現實生活中一般以十進制的形式來表示IP地址,但是由於IP地址都是由數字組成,位數較多不易記憶,所以通過將域名和IP地址產生對應關係,而域名比較容易記憶,通過DNS服務來實現訪問域名達到訪問指定IP地址主機的效果)
3、DNS的結構:
4、瀏覽器訪問互聯網主機的步驟(概述):
①.當使用瀏覽器訪問一個網頁的時候,本機首先查找本地hosts文件,如果本地hosts文件中有映射關係,則優先訪問hosts文件中的域名對應的主機IP地址。
②.當本地hosts中沒有相應的映射關係的時候,本機會向所在網絡的DNS服務器請求要訪問的網頁。如果本地DNS服務器能找到要訪問的網頁主機,則將相應的信息反饋給請求端。如果沒有找到,則本地DNS服務器繼續向根域DNS服務器發出請求。
③、以訪問網易郵箱mail.163.com爲例:當本地DNS服務器向根DNS服務器請求時,根DNS服務器如果不知道網易主機的IP地址,但是卻知道網易主機所在的域.com,接下來就告訴請求端去.com所在的頂級域中查找。
④、當向.com所在域的DNS服務器請求mail.163.com時,如果在.com域的DNS服務器中查不到的,但是可以告訴請求端去163.com這個二級域名所在域的DNS服務器中查找需要的信息。
⑤、而163.com這個域所在的DNS主機下面正好有mail.163.com這臺主機,則此時便將要請求的主機IP地址告訴請求端,然後請求端直接通過該獲取到的IP地址等信息去訪問指定的郵箱資源。
訪問步驟圖例: