一、計算機網(wǎng)絡(概述、簡介)
說起網(wǎng)絡,相信大家都不陌生,把分散在不同地點的計算機設備,通過傳輸介質(zhì)、通信設施和網(wǎng)絡通信協(xié)議,實現(xiàn)資源共享和信息傳輸?shù)南到y(tǒng),我們稱之為:計算機網(wǎng)絡系統(tǒng)。
計算機網(wǎng)絡的最簡單的定義是:一些互相連接的、自治的計算機的集合。
-
互連:是指計算機之間可以通過有線或無線的方式進行數(shù)據(jù)通信;
-
自治:是指獨立的計算機,他有自己的硬件和軟件,可以單獨運行使用;
-
集合:是指至少需要兩臺計算機;
而網(wǎng)絡編程其實就是編寫程序使網(wǎng)絡上的兩個(或多個)設備(如計算機)之間進行數(shù)據(jù)傳輸。
為了使兩個設備之間能進行數(shù)據(jù)傳輸,必須在它們之間建立通信工具(即接口),使彼此之間能進行信息交換,工具包括兩部分:
- 硬件部分:實現(xiàn)節(jié)點之間的信息互傳,比如光貓、網(wǎng)線
- 軟件部分:規(guī)定雙方能進行通信的約定協(xié)議,比如 TCP/IP
從軟件角度看,計算機網(wǎng)絡可以分為網(wǎng)絡體系結(jié)構(gòu)和網(wǎng)絡協(xié)議兩部分。
二、計算機網(wǎng)絡體系結(jié)構(gòu)?
通過網(wǎng)絡將數(shù)據(jù)從一臺主機發(fā)送到另外的主機上,其實是一項非常復雜的操作,必須仔細地協(xié)調(diào)網(wǎng)絡上的物理特性以及所發(fā)送數(shù)據(jù)的邏輯特征。
計算機網(wǎng)絡體系結(jié)構(gòu),其實是計算機網(wǎng)絡層次和協(xié)議的集合。網(wǎng)絡體系結(jié)構(gòu)對計算機網(wǎng)絡實現(xiàn)的功能,以及網(wǎng)絡協(xié)議、層次、接口和服務之間的通信進行了約定描述,但并不涉及具體的實現(xiàn)。
在網(wǎng)絡體系結(jié)構(gòu)中,網(wǎng)絡設備之間的通信被分解為多個層,每一層只與緊挨其上和其下的層對話,層與層之間用接口連接(接口指的是同一節(jié)點內(nèi)相鄰層之間交換信息的連接處,也叫服務訪問點)。
通信的雙方必須具有相同的層次,層次實現(xiàn)的功能由協(xié)議數(shù)據(jù)單元(PDU)來描述,不同系統(tǒng)中的同一層構(gòu)成對等層,對等層之間通過對等層協(xié)議進行通信,理解彼此定義好的規(guī)則和約定。
將網(wǎng)絡進行分層,這樣即使要修改甚至替換某一層的軟件,只要層與層之間的接口保持不變,就不會影響到其他層。
世界上第一個網(wǎng)絡體系結(jié)構(gòu)由 IBM 公司提出,之后其他公司也相繼提出自己的網(wǎng)絡體系結(jié)構(gòu)。為了促進計算機網(wǎng)絡的發(fā)展,國際標準化組織 ISO 在現(xiàn)有網(wǎng)絡的基礎上,提出了不基于具體機型、操作系統(tǒng)或公司的網(wǎng)絡體系結(jié)構(gòu),稱為開放系統(tǒng)互連參考模型,即 OSI/RM(Open System Interconnection Reference Model)。
OSI 模型把網(wǎng)絡通信的工作分為 7 層,分別是應用層、表示層、會話層、傳輸層、網(wǎng)絡層、數(shù)據(jù)鏈路層和物理層。
由于 OSI 模型過于龐大、復雜招致了許多批評,與此相對,美國國防部提出了 TCP/IP 參考模型,把網(wǎng)絡通信的工作分為 4 層,分別是應用層、傳輸層、網(wǎng)絡層、網(wǎng)絡接口層,簡化了 OSI 參考模型。
由于 TCP/IP 參考模型的簡單,獲得了廣泛的應用,并成為后續(xù)網(wǎng)絡通信事實上的標準。
如今用的最多的是TCP/IP體系結(jié)構(gòu),現(xiàn)今規(guī)模最大的、覆蓋全球的、基于TCP/IP的互聯(lián)網(wǎng)并未使用OSI標準。
TCP/IP體系結(jié)構(gòu)相當于將OSI體系結(jié)構(gòu)的物理層和數(shù)據(jù)鏈路層合并為了網(wǎng)絡接口層,并去掉了會話層和表示層。
TCP/IP在網(wǎng)絡層使用的協(xié)議是IP協(xié)議,IP協(xié)議的意思是網(wǎng)際協(xié)議,因此TCP/IP體系結(jié)構(gòu)的網(wǎng)絡層稱為網(wǎng)際層
各個層級職責描述如下:
- 應用層:為 Internet 中的各種網(wǎng)絡應用提供服務,比如 http、ftp 等服務。
- 傳輸層:也被稱為 TCP 層,負責在應用進程之間建立端到端的連接和可靠通信,它只存在與端節(jié)點中,傳輸層涉及兩個協(xié)議,TCP 和 UDP。
- 網(wǎng)絡層:也稱為 IP 層,它是整個 TCP/IP 協(xié)議棧的核心,它的功能是把數(shù)據(jù)路由到目標網(wǎng)絡或主機上。
- 網(wǎng)絡接口層:TCP/IP 協(xié)議對網(wǎng)絡接口層沒有給出具體的描述,對應著 OSI 參考模型,網(wǎng)絡接口層指的的是物理層和數(shù)據(jù)鏈路層的集合。
三、網(wǎng)絡協(xié)議
了解完網(wǎng)絡體系結(jié)構(gòu)后,相信我們對網(wǎng)絡設備之間的數(shù)據(jù)傳輸已經(jīng)有了初步的認識。計算機之間能夠進行相互通信,主要是因為它們都共同遵守一定的規(guī)則,就如同人與人之間能相互交流是因為大家使用了共同的語言文字一樣,這些規(guī)則我們稱之為網(wǎng)絡協(xié)議。
?3.1、IP 協(xié)議
IP 協(xié)議的作用在于把各種數(shù)據(jù)包準備無誤的傳遞給其他設備,其中 IP 地址和 MAC 地址都可以代表設備在網(wǎng)絡中的唯一標識。
先說說 IP 地址。
IP 地址又被稱為邏輯地址,當設備連接上網(wǎng)絡時,由路由器給設備生成一個在當前網(wǎng)絡下唯一的 IP 地址。
同時 IP 地址又分為 IPv4 和 IPv6。
- IPv4:指的是給每個連接在網(wǎng)絡上的主機設備分配一個 32bit 長度的地址,用二進制來表示,由于 1 個字節(jié)等于 8 個 bit,因此 IP 地址可以用 4 個字節(jié)數(shù)表示。例如一個采用二進制形式的 IP 地址
11000000 10101000 00000001 01000010
,這么長的地址處理起來太費勁了,為了方便使用,IP 地址被寫成十進制的形式,中間使用符號.
分隔不同的字節(jié),因此上面的 IP 地址可以用十進制192.168.1.66
表示,IP 地址的這種表示法叫做點分十進制法
,這顯然比 1 和 0 更容易記住。 - IPv6:由于互聯(lián)網(wǎng)的蓬勃發(fā)展,IP 地址的需求量愈來愈大,但是網(wǎng)絡地址資源有限的,使得 IP 的分配越發(fā)緊張。為了擴大地址空間,通過 IPv6 重新定義地址空間,采用 128bit 地址長度,每 16 個字節(jié)一組,分成 8 組十六進制數(shù),這就解決了網(wǎng)絡地址資源數(shù)量不夠的問題,例如
abcd : 1234 : aCA9 : 123 : 4567 : 089 : 0 : 0000
。
以windows
系統(tǒng)為例,可以在 DOS 中輸入ipconfig
命令獲取本機的 IP 地址。
關(guān)于 IP 地址的劃分,也有講究!
-
127.0.0.1
:表示回送地址,也代表本機地址,一般用來測試使用 -
190.168.0.0 – 192.168.255.255
:表示私有地址,屬于非注冊地址,專門為組織內(nèi)部使用,也被稱為內(nèi)網(wǎng)地址
再來說說設備的 MAC 地址。
MAC 地址也叫物理地址、硬件地址,由網(wǎng)絡設備制造商生產(chǎn)時燒錄在網(wǎng)卡的 EPROM 上。 MAC 地址的長度為 48 位(6 個字節(jié)),通常用 12 個十六進制數(shù)來表示,每 2 個十六進制數(shù)之間用冒號隔開,如08:00:20:0A:8C:6D
就是一個 MAC 地址,只要不更改自己的 MAC 地址,MAC 地址在全球是唯一的,但是可以肉眼得出結(jié)論,它比 IPv4 地址更難記憶。
既然 Mac 地址也具有唯一性,為何不能作為 ip 地址資源呢?
- 理由1:IP 地址由網(wǎng)絡服務商生成的邏輯地址,相對于 Mac 地址而言更容易控制和管理網(wǎng)絡設備
- 理由2:IP 地址有 IP 池、IP 段的概念,能通過 IP 地址來定位用戶所在省、市、縣域,而 Mac 地址是由廠商標識的,無法標記用戶的位置信息,只能標記廠商信息
3.2、TCP 協(xié)議
TCP 協(xié)議是面向連接的傳輸層協(xié)議,每次連接都需要經(jīng)過 3 個階段:連接建立、數(shù)據(jù)傳送和連接釋放,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接、然后傳輸數(shù)據(jù)、最后斷開連接,它保證了兩臺計算機之間可靠無差錯的數(shù)據(jù)傳輸。
下面我們一起來看看 TCP 協(xié)議的報文格式,包含了哪些內(nèi)容!
TCP 報文段包括協(xié)議首部和數(shù)據(jù)兩部分,協(xié)議首部的固定部分是 20 個字節(jié),頭部是固定部分,后面是選項部分。
下面是報文段首部各個字段的含義:
- 源端口號以及目的端口號:各占 2 個字節(jié),端口是傳輸層和應用層的服務接口,用于尋找發(fā)送端和接收端的進程,一般來講,通過端口號和IP地址,可以唯一確定一個 TCP 連接,在網(wǎng)絡編程中,通常被稱為一個 socket 接口。
- 序號:Seq 序號,占 4 個字節(jié)。用來標識從 TCP 發(fā)送端向 TCP 接收端發(fā)送的數(shù)據(jù)字節(jié)流序號,發(fā)起方發(fā)送數(shù)據(jù)時對此進行標記。
- 確認序號:Ack 序號,占 4 個字節(jié)。包含接受端所期望收到的下一個序號。只有 ACK 標記位為 1 時,確認序號字段才有效,因此,確認序號應該是上次已經(jīng)成功收到數(shù)據(jù)字節(jié)序號加 1,即 Ack = Seq + 1。
- 數(shù)據(jù)偏移:占 4 個字節(jié),用于指出 TCP 首部長度,若不存在選項,則這個值為 20 字節(jié),數(shù)據(jù)偏移的最大值為 60 字節(jié)。
- 保留字段:占 6 位,暫時可忽略,值全為 0。
- 六位標志位:值內(nèi)容含義如下
- URG(緊急):為1時表明緊急指針字段有效
- ACK(確認):為1時表明確認號字段有效
- PSH(推送):為1時接收方應盡快將這個報文段交給應用層
- RST(復位):為1時表明TCP連接出現(xiàn)故障必須重建連接
- SYN(同步):在連接建立時用來同步序號
- FIN(終止):為1時表明發(fā)送端數(shù)據(jù)發(fā)送完畢要求釋放連接
- 窗口:占 2 個字節(jié),用于流量控制和擁塞控制,表示當前接收緩沖區(qū)的大小。
- 校驗和:占 2 個字節(jié),范圍包括首部和數(shù)據(jù)兩部分
- 緊急指針:指出了緊急數(shù)據(jù)的末尾在報文段中的位置,和 URG 搭配使用
- 選項和填充:是可選的,默認情況是不選。
向深入的了解 TCP 原理的同學,可以看看這篇博客文章。
下面我們要重點說說 TCP 中的三次握手與四次揮手,因為這種數(shù)據(jù)傳輸模型保證了兩臺計算機之間可靠無差錯的數(shù)據(jù)傳輸。
當兩個設備之間準備傳輸時,TCP 會建立連接,創(chuàng)建連接的階段需要三次握手,過程如下:
- 第一次握手:客戶端向服務器端發(fā)出連接請求,等待服務器確認
- 第二次握手:服務器端收到請求后,向客戶端回送一個確認,通知客戶端收到了連接請求
- 第三次握手:客戶端再次向服務器端發(fā)送確認信息,確認連接
完成以上 3 次握手之后,可靠性連接建立完成,準備進行數(shù)據(jù)傳輸。
當數(shù)據(jù)傳輸完畢之后,準備釋放連接,連接的釋放需要四次揮手,過程如下:
- 第一次揮手:客戶端向服務器端發(fā)出請求切斷連接,等待服務器確認
- 第二次揮手:服務器端收到請求后,向客戶端回送一個確認信息,并同意關(guān)閉請求
- 第三次揮手:服務器端再次向客戶端發(fā)出請求切斷連接,等待客戶端確認
- 第四次揮手:客戶端收到請求后,向服務器端回送一個確認信息,并同意關(guān)閉請求
完成以上 4 次揮手之后,連接釋放完成。
3.3、UDP 協(xié)議
UDP 協(xié)議是 TCP/IP 協(xié)議簇中面向無連接的傳輸層協(xié)議,特點如下:
- 1.傳輸數(shù)據(jù)之前,源端和終端不建立連接,當它想傳送時就簡單地去抓取來自應用程序的數(shù)據(jù),并盡可能快地把它扔到網(wǎng)絡上。在發(fā)送端,UDP 傳送數(shù)據(jù)的速度僅僅是受應用程序生成數(shù)據(jù)的速度、計算機的能力和傳輸帶寬的限制;在接收端,UDP 把每個消息段放在隊列中,應用程序每次從隊列中讀一個消息段。
- 2.由于傳輸數(shù)據(jù)不建立連接,因此也就不需要維護連接狀態(tài),包括收發(fā)狀態(tài)等,因此一臺服務器可同時向多個客戶端傳輸相同的消息。
- 3.UDP 信息包的標題很短,只有 8 個字節(jié),相對于 TCP 的 20 個字節(jié)信息包的額外開銷很小。
- 4.吞吐量不受擁擠控制算法的調(diào)節(jié),只受應用軟件生成數(shù)據(jù)的速率、傳輸帶寬、源端和終端主機性能的限制。
- 5.UDP 使用盡量最大努力交付,即不保證可靠交付,因此主機不需要維持復雜的鏈接狀態(tài)表
- 6.UDP 是面向報文的。發(fā)送方的 UDP 對應用程序交下來的報文,在添加首部后就向下交付給 IP 層。既不拆分,也不合并,而是保留這些報文的邊界,因此,應用程序需要選擇合適的報文大小。
下面我們一起來看看 UDP 協(xié)議的報文格式,包含了哪些內(nèi)容!
UDP 協(xié)議由兩部分組成:首部和數(shù)據(jù)。其中,首部僅有 8 個字節(jié),包括源端口和目的端口、長度(UDP用于數(shù)據(jù)報的長度)、校驗和。
UDP 協(xié)議沒有像 TCP 協(xié)議那樣的三次握手、四次揮手操作,數(shù)據(jù)傳輸模型非常簡單,它只管發(fā)和收,總結(jié)下來,兩者具體的區(qū)別如下:
- 1.TCP 基于連接,UDP 是無連接的;
- 2.對系統(tǒng)資源的要求,TCP 較多,UDP 較少
- 3.UDP 程序結(jié)構(gòu)較簡單
- 4.TCP 是流模式,而 UDP 是數(shù)據(jù)報模式
- 5.TCP 保證數(shù)據(jù)正確性,而 UDP 可能丟包;TCP 保證數(shù)據(jù)順序,而 UDP 不保證
- 6.TCP 協(xié)議由于更安全、更可靠,應用場景比較廣泛,例如上傳文件、下載文件、瀏覽網(wǎng)頁。
- 7.UDP 協(xié)議雖然不可靠,但是傳輸效率更高,實際應用場景也比較多,例如視頻會議、在線游戲、語音聊天等
- 8.UDP 協(xié)議要求包小于 64K,TCP 沒有限定
3.4、HTTP 協(xié)議
HTTP 協(xié)議,也俗稱超文本傳輸協(xié)議,它是基于 TCP 協(xié)議之上的請求/響應式的應用層協(xié)議,使用 TCP/IP 來傳輸數(shù)據(jù),也是互聯(lián)網(wǎng)上應用最為廣泛的一種網(wǎng)絡協(xié)議。
HTTP 協(xié)議同時也是 Web 瀏覽器和 Web 服務器之間通信的標準協(xié)議。HTTP 指定客戶端與服務器如何建立連接、客戶端如何從服務器請求數(shù)據(jù),服務器如何響應請求,以及最后如何關(guān)閉連接。
對于從客戶端到服務器的每一個請求,都有 4 個步驟:
- 1.默認情況下,客戶端在端口 80 打開與服務器的一個 TCP 連接,不過 URL 中還可以指定其他端口。
- 2.客戶端向服務器發(fā)送消息,請求指定路徑上的資源。這個資源包括一個首部,可選地(取決于請求的性質(zhì))還可以有一個空行,后面是這個請求的數(shù)據(jù)。
- 3.服務器向客戶端發(fā)送響應,響應以響應碼開頭,后面是包含數(shù)據(jù)的首部、一個空行以及所請求的文檔或錯誤消息。
- 4.服務器關(guān)閉連接。
現(xiàn)在使用的 HTTP 協(xié)議是 HTTP/1.1 版本,1997 年之前采用的是 HTTP/1.0 版本,兩者區(qū)別在于:HTTP 連接在 1.0 版本中采用非持續(xù)連接工作方式,1.1 版本采用的是持續(xù)連接工作方式。持續(xù)連接是指服務器在發(fā)送響應后仍然在一段時間內(nèi)保持這條由 TCP 傳輸層協(xié)議建立起來的連接,使客戶端和服務器可以繼續(xù)在這條連接上傳輸 HTTP 報文,避免重復的創(chuàng)建連接和釋放連接。
是否采用持續(xù)連接工作方式,1.0 中默認是關(guān)閉的,需要在 HTTP 頭加入Connection:Keep-Alive
,才能啟用Keep-Alive
。HTTP1.1 中默認啟用Keep-Alive
,如果加入Connection:close
,請求完會關(guān)閉連接。目前大部分瀏覽器都是用 HTTP1.1 協(xié)議,也就是說默認都會發(fā)起Keep-Alive
的連接請求了,是否能完成一個完整的Keep-Alive
連接就看服務器設置情況。
下面我們一起來看看 HTTP 協(xié)議的報文格式,HTTP 報文主要包括:請求報文和響應報文兩種。
HTTP 請求報文的格式如下:
HTTP 請求報文由請求行、首部行和實體主體組成,由瀏覽器發(fā)送給服務器。上面這張圖中 SP 表示空格,cr lf 表示回車和換行。下圖是谷歌瀏覽器內(nèi)訪問服務器查看的 HTTP 請求報文例子:
HTTP 響應報文的格式如下:
上面這張圖是 HTTP 響應報文,它由狀態(tài)行、首部行和實體主體組成。下圖是谷歌瀏覽器內(nèi)訪問服務器查看的 HTTP 響應報文例子:
在上面的 HTTP 請求報文例子中,我們可以看到請求方法是 GET,它表示請求由 URL 所標志的信息,除了 GET,還有其他幾種常用的方法。
在 HTTP 響應報文的例子中,我們可以看到狀態(tài)碼是 200,表示響應成功,除此之外,還有其他的狀態(tài)碼,總共 5 大類。
熟悉 HTTP 協(xié)議的同學可能都知道,HTTP 協(xié)議是以明文方式發(fā)送內(nèi)容,不提供任何方式的數(shù)據(jù)加密,如果攻擊者截取了 Web 瀏覽器和網(wǎng)站服務器之間的傳輸報文,就可以直接讀懂其中的信息,因此 HTTP 協(xié)議不適合傳輸一些敏感信息,比如信用開號、密碼等。
為了解決 HTTP 協(xié)議的這一缺陷,需要使用另一種協(xié)議:HTTPS 協(xié)議。
HTTPS(全稱:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全為目標的 HTTP 通道,簡單來說就是 HTTP 的安全版。即在 HTTP 下加入 SSL 協(xié)議,SSL 依靠證書來驗證服務器的身份,并為瀏覽器和服務器之間的通信加密。
HTTPS 和 HTTP 的區(qū)別主要為以下三點:
- 1.http 是超文本傳輸協(xié)議,信息是明文傳輸;https 協(xié)議是由 http + ssl 協(xié)議構(gòu)建的可進行加密傳輸、身份認證的網(wǎng)絡協(xié)議,信息是密文傳輸,比 http 協(xié)議安全。
- 2.https 協(xié)議需要到 ca 申請證書,一般免費證書很少,需要繳費
- 3.http 和 https 使用的默認端口也不一樣,前者是 80,后者是 443
更多的網(wǎng)絡協(xié)議介紹,有興趣的朋友可以看看這篇博客文章。
四、網(wǎng)絡編程
看完以上信息之后,要想讓網(wǎng)絡中的計算機能夠互相通信,少不了以下三個核心要素:
- IP 地址:指的是計算機在網(wǎng)絡中的唯一標識,目前使用最廣泛的是 IPV4
- 端口:指的是計算機中應用程序的唯一標識,用兩個字節(jié)表示的整數(shù),它的取值范圍是
0 - 65535
- 協(xié)議:指的是通過什么協(xié)議傳輸數(shù)據(jù),例如 TCP、UDP
Java 語言對網(wǎng)絡編程提供了良好的支持,通過其提供的接口我們可以很方便地進行網(wǎng)絡編程。
下面我們一起來看看相關(guān)的代碼實例!
4.1、URL 介紹
URL 表示統(tǒng)一資源定位符,指向萬維網(wǎng)上“資源”的指針。
一個標準的 URL 包括以下幾個部分:
- protocol:方案或協(xié)議
- host:主機或者 IP 地址
- port:端口
- path:路徑
- parameter:查詢參數(shù)
- anchor:錨點
在 www 上,每一信息資源都有統(tǒng)一且唯一的地址。
代碼實例如下:
public static void main(String[] args) throws MalformedURLException {
URL url = new URL("http://www.baidu.com:80/index.html?uname=dream&age=18#a");
// 獲取四個值:協(xié)議、域名、端口、請求資源
System.out.println("協(xié)議:" + url.getProtocol());
System.out.println("域名|IP:" + url.getHost());
System.out.println("端口:" + url.getHost());
System.out.println("請求資源:" + url.getPath());
// 參數(shù)
System.out.println("參數(shù):" + url.getQuery());
// 錨點
System.out.println("錨點:" + url.getRef());
}
輸出結(jié)果:
協(xié)議:http
域名|IP:www.baidu.com
端口:www.baidu.com
請求資源:/index.html
參數(shù):uname=dream&age=18
錨點:a
4.2、InetAddress 介紹
為了方便我們對 IP 地址的獲取和操作,Java 提供了一個類InetAddress
供我們使用。
代碼實例如下:
public static void main(String[] args) throws UnknownHostException {
InetAddress address = InetAddress.getByName("www.baidu.com");
System.out.println("主機名:" + address.getHostName());
System.out.println("IP地址: " + address.getHostAddress());
}
輸出結(jié)果:
主機名:www.baidu.com
IP地址: 14.119.104.254
4.3、IntetSocketAddress 介紹
IntetSocketAddress 包含 IP 和端口信息,常用于 Socket 通信。此類實現(xiàn) IP 套接字地址(IP 地址+端口號),不依賴任何協(xié)議。
代碼實例如下:
public static void main(String[] args) {
// 指定ip、端口
InetSocketAddress socketAddress = new InetSocketAddress("14.119.104.254",80);
System.out.println("主機名:" + socketAddress.getHostName());
System.out.println("地址:" + socketAddress.getAddress());
System.out.println("端口號:" + socketAddress.getPort());
System.out.println("==================================");
// 指定主機名、端口
InetSocketAddress socketAddress2 = new InetSocketAddress("www.baidu.com",80);
System.out.println("主機名:" + socketAddress2.getHostName());
System.out.println("地址:" + socketAddress2.getAddress());
System.out.println("端口號:" + socketAddress2.getPort());
}
輸出結(jié)果:
主機名:14.119.104.254
地址:14.119.104.254/14.119.104.254
端口號:80
==================================
主機名:www.baidu.com
地址:www.baidu.com/14.119.104.254
端口號:80
4.4、Socket 介紹
Java 的網(wǎng)絡編程主要涉及到的內(nèi)容就是 Socket 編程。
Socket,也被稱為套接字,它是網(wǎng)絡通信中兩臺主機之間邏輯連接的端點的抽象表示,包含了進行網(wǎng)絡通信必須的五種信息:連接使用的協(xié)議、本地主機的 IP 地址、本地進程的協(xié)議端口、遠程主機的 IP 地址、遠程進程的協(xié)議端口。
實際上,Socket 是對 TCP/IP 協(xié)議的封裝實現(xiàn),Socket 本身并不是協(xié)議,而是一個可以調(diào)用的接口(API);通過 Socket,程序員可以更方便地使用 TCP/IP 協(xié)議棧里面的邏輯,比如 create、accept、send、read 和 write 等等。
關(guān)于 Socket 和 TCP/IP 協(xié)議關(guān)系,如果感覺很抽象,你可以這樣理解。TCP/IP 協(xié)議棧是網(wǎng)絡信息傳輸?shù)囊粋€運行機制方案,而 Socket 是 TCP/IP 協(xié)議棧的具體技術(shù)編程實現(xiàn)。
Socket 編程主要涉及到客戶端和服務端兩個方面,以 TCP 協(xié)議通信為例,首先是在服務器端創(chuàng)建一個服務器套接字(ServerSocket),并把它附加到一個端口上,服務器從這個端口監(jiān)聽連接。端口號的范圍是 0 到 65536,但是 0 到 1024 是為特權(quán)服務保留的端口號,在指定端口時盡量避開這個區(qū)間,我們可以選擇一個當前沒有被其他進程使用的端口。
客戶端請求與服務器進行連接的時候,根據(jù)服務器的域名或者 IP 地址,加上端口號,打開一個 Socket 套接字。當服務器接受連接后,服務器和客戶端之間的通信就可以像輸入輸出流一樣進行操作。
Socket 通信模式圖
下面我們一起來看看具體的代碼示例,更容易理解。
4.4.1、TCP 協(xié)議通信介紹
TCP 協(xié)議可以保證數(shù)據(jù)可靠、安全的傳輸給另一臺主機,實際應用非常廣泛,下面我們一起來看看如何實踐。
首先創(chuàng)建一個服務端,代碼實例如下:
public class ServerAdminTest {
public static void main(String[] args) throws IOException {
//使用需要捕獲異常,因為可能會存在無法連接的情況
ServerSocket serverSocket = new ServerSocket(8080);
//測試語句
System.out.println("本地服務器已開啟");
while (true){
try {
//等待客戶端的連接
Socket socket = serverSocket.accept();
System.out.println("已收到客戶機請求");
//輸入流,讀取數(shù)據(jù)用的
InputStream inputStream = socket.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
//讀取客戶機發(fā)送來的消息,設置判斷,只有客戶機有發(fā)送消息才做輸出語句
String info;
while((info = reader.readLine()) != null) {
System.out.println("收到客戶機消息:"+info);
}
//輸出流,發(fā)送數(shù)據(jù)用的
OutputStream outputStream = socket.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);
//給客戶機發(fā)送一段消息
printWriter.write("hello,我是服務端,已收到你的信息!");
printWriter.flush();
//關(guān)閉輸入、輸出流
reader.close();
printWriter.close();
//最后關(guān)閉網(wǎng)絡連接
socket.close();
} catch (Exception e){
e.printStackTrace();
}
}
}
}
然后創(chuàng)建一個客戶端,代碼實例如下:
public class ClientAdminTest {
public static void main(String[] args) throws IOException {
//連接到目標服務器
Socket client = new Socket("127.0.0.1",8080);
System.out.println("客戶機已經(jīng)與服務器建立鏈接");
//創(chuàng)建輸出流
OutputStream outputStream = client.getOutputStream();
PrintWriter printWriter = new PrintWriter(outputStream);
//輸出這段話
printWriter.write("hello,我是客戶機!");
printWriter.flush();
//關(guān)閉輸出,不再輸出更多數(shù)據(jù),如果不關(guān)閉,就會出現(xiàn)服務器無法判斷客戶機何時會結(jié)束發(fā)送消息,從而無法進行回應。就像一個人和你打電話的時候一直在說話,你無法在這段時間如回復他。
client.shutdownOutput();
//創(chuàng)建輸入流
InputStream inputStream = client.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
//讀取服務端發(fā)送過來的消息
String info;
while((info = reader.readLine()) != null) {
System.out.println("接受服務器發(fā)送的消息:"+info);
}
//關(guān)閉輸入、輸出流
reader.close();
printWriter.close();
//最后關(guān)閉網(wǎng)絡連接,就和打完電話之后要掛斷電話一樣
client.close();
}
}
最后依次先后啟動服務端、客戶端,看看控制臺輸出結(jié)果如何。
服務端輸出內(nèi)容如下:
本地服務器已開啟
已收到客戶機請求
收到客戶機消息:hello,我是客戶機!
客戶端輸出內(nèi)容如下:
客戶機已經(jīng)與服務器建立鏈接
接受服務器發(fā)送的消息:hello,我是服務端,已收到你的信息!
Socket 對 TCP/IP 協(xié)議里面的創(chuàng)建連接、釋放連接進行了隱藏,開發(fā)者只需要關(guān)注數(shù)據(jù)傳輸即可。
4.4.2、UDP 協(xié)議通信介紹
UDP 協(xié)議是一種不可靠的網(wǎng)絡協(xié)議,它在通信的兩端各建立一個 Socket 對象,但是這兩個 Socket 只是發(fā)送、接收數(shù)據(jù)的對象,沒有客戶端和服務器概念。
盡管如此,但是它傳輸速度高效,實際應用也非常廣,下面我們一起來看看如何實踐。
首先創(chuàng)建一個接受端,代碼實例如下:
public class UDPReceive {
public static void main(String[] args) throws IOException {
System.out.println("接收方啟動中...");
// 1、創(chuàng)建接收端的Socket對象(DatagramSocket)
DatagramSocket ds = new DatagramSocket(9999);
// 2、創(chuàng)建一個數(shù)據(jù)包,用于接收數(shù)據(jù)
byte[] bys = new byte[1024];
DatagramPacket dp = new DatagramPacket(bys, 0, bys.length);
// 3、調(diào)用DatagramSocket對象的方法接收數(shù)據(jù)
ds.receive(dp);
// 4、解析數(shù)據(jù)包,并把數(shù)據(jù)在控制臺顯示
System.out.println("數(shù)據(jù)是:" + new String(dp.getData(), 0, dp.getLength()));
// 5、關(guān)閉接收端,釋放資源
ds.close();
}
}
然后創(chuàng)建一個發(fā)送端,代碼實例如下:
public class UDPSend {
public static void main(String[] args) throws Exception {
System.out.println("發(fā)送方啟動中...");
// 1、使用DatagramSocket指定端口,創(chuàng)建發(fā)送端
DatagramSocket client = new DatagramSocket(8888);
// 2、準備數(shù)據(jù),一定要轉(zhuǎn)成字節(jié)數(shù)組
String data = "Java YYDS";
// 3、封裝成DatagramPacket包裹,需要指定目的地(IP+port)
byte[] bys = data.getBytes();
DatagramPacket packet = new DatagramPacket(bys, 0, bys.length, new InetSocketAddress("127.0.0.1", 9999));
// 4、發(fā)送包裹 void send(DatagramPacket p)
client.send(packet);
// 5、釋放資源
client.close();
}
}
最后依次先后啟動接受端、發(fā)送端,看看控制臺輸出結(jié)果如何。
接受端輸出內(nèi)容如下:
接收方啟動中...
數(shù)據(jù)是:Java YYDS
?更多關(guān)于計算機網(wǎng)絡學習查詢相關(guān)資料如文章來源:http://www.zghlxwxcb.cn/news/detail-811901.html
計算機網(wǎng)絡整理筆記 - 專題 - 簡書文章來源地址http://www.zghlxwxcb.cn/news/detail-811901.html
到了這里,關(guān)于計算機網(wǎng)絡編程的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!