? ? ? ? 接下來說Java中非常重要的一個技術部分,就是網絡編程。Java語言涵蓋的領域非常廣,對于網絡這一塊它也不示弱,Java也可以完成網絡通訊的部分。
????????我們以前寫代碼是單機版的,比如把代碼從C盤拷貝到D盤。那么能不能從我的機器上發條信息,到張三的機器上,張三再給我回復條信息,讓我們兩個機器之間利用Java語言實現數據的通訊,而數據通訊的原理就是數據傳輸。那么它和我們之前本機上數據傳輸的唯一不同就是涉及到了網絡。
? ? ? ? 畫圖來表示一下通訊的過程:?
????02-網絡編程(概述2)
? ? ? ? IP地址分四段組成,每一段其實就是一個字節,一個字節最大值就是255(8個1)。
? ? ? ? 有一個IP地址非常特殊,就是127.0.0.1,這個是一個本地回環地址。也就是說,本地沒有配任何IP地址的情況下,本機默認的IP地址就是127.0.0.1。
? ? ? ? 可以PING它來測試網卡:
? ? ? ? 后面4段的IP地址已經不夠用了(IPV4),所以就出現了6段的IP地址(IPV6),IPV6不光包含數字,還包含字母,它排列組合之后地址非常多,足夠使用了。這是我們新段地址(IPV6)和老段地址(IPV4)的區別。
? ? ? ? 下面說端口,端口數字的選擇范圍為0-65535。通常0-1024這個范圍內的端口被系統所保留了。
????03-網絡編程(網絡模型)
? ? ? ? 說完了網絡傳輸的基本三要素:IP地址、端口、協議以外,我們就要說一說具體的傳輸方式。
? ? ? ? 首先說一下網絡模型。
? ? ? ? 網絡在傳輸的過程中,因為每層次所對應的功能不一樣,而有了層次的細致劃分。
? ? ? ? 網絡參考模型:
? ? ? ? 剛開始7層參考模型數據封包的過程:
? ? ? ? 數據拆包的過程:
? ? ? ? 后來有了簡化的參考模型,將應用層、表示層、會話層合成了應用層,將數據鏈路層和物理層合成了主機至網絡層,而傳輸層和網絡層(網際層)因為比較重要依然單獨存在。簡化后的參考模型只有四層了。
? ? ? ? 那我們現在主要學習哪一層呢?
? ? ? ? 因為我們是學軟件的,所以硬件部分主機至網絡層不用管,主要學應用層、傳輸層、網際層,其中傳輸層和網際層是我們學習的重點,之前我們寫的程序都在這一層。
? ? ? ? 而如果學Java Web開發的話,就主要在應用層混。
? ? ? ? 所以說,我們現在要玩的是軟件中比較底層的(傳輸層和網際層),而應用層是基于我們學的這些,就它封裝了。所以應用層更簡單。
? ? ? ? 而每個層都有自己的協議(通訊規則),傳輸層最常見的協議就是TCP和UDP,網際層最常見的協議就是IP,應用層最常見的協議就是HTTP和FTP。
? ? ? ? 我們接下來的計劃是,先學網際層和傳輸層,掌握它們的特點后,再學應用層。
????04-網絡編程(IP地址)
? ? ? ? 我們知道網絡通訊有三個要素:IP地址、端口號、傳輸協議。那么如何用Java來操作它呢?我們想到了封裝成對象。
? ? ? ? 先來看一下這幾個要素的特點。
? ? ? ? IP地址:
? ? ? ? 1,是網絡中設備的標識。
? ? ? ? 2,不易記憶,可用主機名。
? ? ? ? 3,本地回環地址:127.0.0.1? 主機名:localhost
? ? ? ? 主機名和IP地址是相對應的,每臺計算機都有自己的主機名:
? ? ? ? 那么IP到底用什么來表示呢?
? ? ? ? 我們來java.net包中看一看。
? ? ? ? net包中用于描述IP的對象是InetAddress,它有兩個子類,“4”和“6”:
? ? ? ? 打印本地的主機名和地址:
? ? ? ? 還可以用非靜態的方法單獨獲取主機名和地址:
? ? ? ? 有沒有辦法獲取任意一臺主機的主機名和地址呢?
? ? ? ? 我們想一想,如果存在這個方法,那么這個方法的返回值類型是IP地址對象(即InetAddress),另外任意一臺主機的話,為了清除到底是哪一臺,必須將這臺主機指定進去傳進去,所以這個方法還需要有參數。分析得到這兩個要素,我們在方法中找一找有沒有符合則兩個要素的方法。
? ? ? ? 我們看到一個,傳入主機名返回IP地址對象的:
? ? ? ? 代碼演示:
? ? ? ? 可是這里我們還是用自己的本機試的,我們試試其他機子:
? ? ? ? 運行的很慢:
? ? ? ? 如果這個地址和它對應的主機名沒有在網絡上,那么拿這個地址出去找就沒有解析成功。那為什么我們本機的可以解析這個不能解析呢?因為本機的信息本機上都有,而另外一臺機子的信息沒有找到,所以返回的主機名還是IP地址。
? ? ? ? 其實只要連上網,我們可以直接獲取百度主機名和地址(不用寫它的IP地址,直接寫它的域名就好了,它就和IP地址相對應),可是百度面向的人群那么大,它肯定有多臺主機,而且一個地址有可能對應著多個服務器,所以有可能返回來的IP對象不唯一,所以這里還有一個傳入主機名返回數組的方法:
????05-網絡編程(TCP和UDP)? ? ? ?
? ? ? ? 端口號:
? ? ? ? 1,是用于標識進程的邏輯地址,不同進程的標識。
? ? ? ? 2,有效端口:0~65535,其中0~1024為系統使用或保留端口。
? ? ? ? 端口就是一個數字標識,所以它沒有必要封裝成對象。
? ? ? ? 下面重點說一下傳輸協議。
? ? ? ? 傳輸協議:
? ? ? ? 1,它是通訊的規則。
? ? ? ? 2,常見協議:TCP,UDP。
? ? ? ? TCP和UDP到底有什么區別呢?
? ? ? ? UDP是面向無連接的,將數據封裝包中,然后貼上小紙條,標明它的地址和端口。一般傳輸都有兩端:發送端和接收端,如果用UDP傳輸,那么對方在不在都無所謂,我就是發我的,把數據打成一個包發出去,你在就收到了,不在這個包就丟掉。另外,在傳輸的時候也可能存在地址不存在的情況。
? ? ? ? UDP的特點:
? ? ? ? 1,將數據及源和目的封裝在數據包中,不需要建立連接。
? ? ? ? 2,每個數據包的大小限制在64k內。
? ? ? ? 3,因無連接,是不可靠協議,容易丟包。
? ? ? ? 4,不需要建立連接,速度快。
? ? ? ? 我們聊天、視頻共享就是UDP,在不在不重要,把數據發出去就行了。
? ? ? ? 下面說TCP,TCP必須是面向連接的。也就是說,如果用TCP通訊的話,對方必須在,對方不在就不行。它比較可靠,如果單方面斷開的話,數據就不傳了。必須形成通路,數據才能傳輸。
? ? ? ? 那怎么確認對方在不在呢?
? ? ? ? 我們通過三次握手來完成。
? ? ? ? TCP的特點:
? ? ? ? 1,建立連接,形成傳輸數據的通道。
? ? ? ? 2,在連接中進行大數據量傳輸。
? ? ? ? 3,通過三次握手完成連接,是可靠協議。
? ? ? ? 4,必須建立連接,效率會稍低。
? ? ? ? TCP相當于打電話,只有對方接電話才能通話。
????06-網絡編程(Socket)
? ? ? ? 下面說Socket,我們說的網絡編程,其實就是Socket編程。
? ? ? ? Socket就是為網絡服務提供的一種機制。
? ? ? ? 通信的兩端都有Socket,有了Socket才能建立連接。它就相當于碼頭,有了碼頭,船只才能在兩個碼頭間通行、搬運貨物。
? ? ? ? 網絡通信其實就是Socket間的通信。
? ? ? ? 數據在兩個Socket間通過IO傳輸。
????07-網絡編程(Udp-發送端)
? ? ? ? Socket有了,但是傳輸協議不同,每個傳輸協議都有自己建立端點的方式。
? ? ? ? 我們先來說UDP的Socket服務的建立。
? ? ? ? 我們看到java.net包中有兩個socket對象,一個叫DatagramSocket:
? ? ? ? 這個對象既能發送又能接收,如果有兩個端點發送和接收數據,那這兩個端點每個端點都要有這個對象。
? ? ? ? 那么發送和接收什么數據是不是就要指定一下呢:
? ? ? ? UDP要把數據封裝成包發過去,其中包括擴對方的地址和端口、自己的地址和端口,都在這個數據包中,這個數據包很復雜,所以把這個數據包封裝成了對象,這個對象就是DatagramPacket:
????????接下來要寫代碼,我們的需求是:
????????代碼:
????????不要忘記導入包:
? ? ? ? 因為面向無連接,所以這個數據就丟失了,那怎么能夠讓這個數據被收到呢?
????08-網絡編程(Udp-接收端)
? ? ? ? 之所以數據丟失是因為接收端沒開,我們這節課來寫接收端的代碼,為了看起來更直觀就將接收端代碼和發送端代碼寫在同一個java文件中了,但是它們是兩段獨立運行的程序,所以里面都有自己的主函數。
? ? ? ? 接收端的需求和思路:
? ? ? ? 定義udpsocket服務的時候,通常會監聽一個端口,其實就是給這個接收網絡應用程序定義數字標識,方便于明確哪些數據過來該應用程序可以處理。
? ? ? ? 代碼:
? ? ? ? 接下來要運行了,開啟兩個dos命令行:
? ? ? ? 這里的1093是系統隨機為發送端產生的數字標識(在我們沒有為發送端指定數字標識的前提下):
? ? ? ? 多運行幾次我們發現每一次都不一樣:
????????若我們為發送端指定了數字標識8888:
? ? ? ? 則這里就會顯示我們指定的數字標識,不用系統隨機分配了:
????09-網絡編程(UDP-鍵盤錄入方式數據)
? ? ? ? 在這里加上while(true)循環:
? ? ? ? 我們在這里加上while(true)循環的好處是,接收端運行的時候運行一次就OK了,因為receive方法是阻塞式方法,它會一直等著,我們運行一次之后它就一直等著,每次一有數據傳輸過來它都可以接收到,實現了重復接收:
????????但是我們發現老師每次發送的都是同一句話,能不能發送點別的呢?
????????那我們把這里改一下重新編譯運行發送?
? ? ? ? 可是每次只能發一句,而且每發一句就要重新編譯運行,好麻煩呢。
? ? ? ? 那我們能不能通過鍵盤錄入呢?
? ? ? ? 代碼:
? ? ? ? 運行效果:
? ? ? ? 我們剛剛用的地址是192.168.1.254,最后一段的取值中0和255比較特別,192.168.1.0代表這一個網絡段,而192.168.1.255是這一個網絡段的廣播地址,就是給這個網絡段的所有地址讀發送。
? ? ? ? 改成這個地址就可以實現群聊了:
????10-網絡編程(UDP-聊天)
? ? ? ? 我們剛剛的效果是仿造的聊天,但是是在兩個窗口實現,能不能一個窗口實現呢?
? ? ? ? 這個時候就要用到多線程的技術,一個線程控制收,一個線程控制發。
? ? ? ? 因為收和發動作是不一致的,所以要定義兩個run方法,而且這兩個方法要封裝到不同的類中。
? ? ? ? 記得導入這兩個包:
? ? ? ? 運行效果:
? ? ? ? 但是有一個問題,我們正在寫數據還沒有回車發送的時候,如果地方此時發送了一條消息就會出現下面的問題,和我們正在編輯的數據混在一起:
? ? ? ? 這都是因為,發送端和接收端混在同一個面積區域中,如果我們做一個圖形化界面,將發送端和接收端分成兩個區域,就解決了這個問題。
????11-網絡編程(TCP傳輸)
? ? ? ? 說完了UDP傳輸,我們說TCP傳輸。
? ? ? ? 實在好著急,下面是純截屏,好著急好著急。
? ? ? ? 演示TCP傳輸:
????12-網絡編程(TCP傳輸2)
? ? ? ? 剛才只是客戶端給服務端發了信息,但是服務端并沒有給客戶端反饋,下面我們要實現反饋動作。
? ? ? ? 需求描述和實現步驟:
? ? ? ? 代碼:
? ? ? ? 運行結果:
????13-網絡編程(TCP練習)
? ? ? ? 接下來通過一個練習來用到開發中常用到的對象。
? ? ? ? 需求描述:? ? ? ??
? ? ? ? 代碼:
? ? ? ? 運行之后發現客戶端發信息,服務端并不能收到。是哪里出問題了呢?
? ? ? ? 首先,考慮一下客戶端到底發出去了沒有呢??
? ? ? ? 客戶端的數據寫入了緩沖區,在這里恍然大悟,剛剛忘記寫flush了,我們把flush加上。
? ? ? ? 另一個問題就是服務端讀數據判斷結束的標記是換行標記:
? ? ? ? 而客戶端發送數據后面并沒有換行標記,于是我們再加上換行符,修改后的代碼如下:
? ? ? ? 運行,服務端收到了客戶端的數據,但是客戶端并沒有收到服務端返回的大寫數據。
? ? ? ? 我們又忘記給服務端flush了,因為它的數據也是寫在緩沖區中呢,另外,和服務端一樣,客戶端判斷數據結束的標記也是換行符,所以我們也加上換行符,代碼修改如下(和剛剛客戶端代碼添加的內容是一樣的):
? ? ? ? 運行:
? ? ? ? 該例子中出現的問題:
? ? ? ? 另外,這個例子中的還有可以簡化的代碼,客戶端和服務端簡化的部分都一樣,這里以服務端部分示例:
????14-網絡編程(TCP復制文件)
? ? ? ? 剛才的例子是通過鍵盤錄入,從客戶端向服務端發數據。下面再說一個例子,將客戶端的數據發送到服務端,再由服務端將數據存到一個文件中去,這就相當于數據拷貝。
? ? ? ? 以前是將文件從C盤拷到D盤,現在是將文件從我的機子中拷到你的機子中,其中加入了網絡的技術,但是還是IO。
? ? ? ? 代碼:
? ? ? ? 記得導包哦:
? ? ? ? 但是程序一直停不下來,沒有像我們預料中那樣出現上傳成功的文字:
? ? ? ? 但是我們去文件夾重看了一下,發現文件已經成功存入了呢。
? ? ? ? 原來,是因為代碼中沒有結束標記,于是我們在客戶端的代碼中,在文件中數據全部讀取完畢之后,加上結束標記“over”:
? ? ? ? 在服務端中判斷結束標記“over”,若碰到則結束:
? ? ? ? 但是如果這個文件中本身就正好包含“over”,和我們的結束標記“over”重名了怎么辦呢?
? ? ? ? 不如我們用下面這串字符:
? ? ? ? 但即使是這串字符,這種定義方式也是容易重復的,我們用一個唯一的標記:時間戳,因為每個時刻的時間是唯一的。
? ? ? ? 注意,在客戶端代碼中,發送數據之前需要先將時間戳發給服務端,讓它知道這是結束標記,然后客戶端中讀完了源文件的數據,再在后面補上時間戳作為結束標記,下面是客戶端和服務端代碼的修改,客戶端:
? ? ? ? 服務端:
? ? ? ? 其實,這還是一個比較麻煩的方法,我們只是做一下了解(好氣喔!)
? ? ? ? 其實有更簡單的方法,而且只需要修改客戶端中的代碼,且只用加上這一句代碼:
? ? ? ? OK:
? ? ? ? day23的課程實在太倉促了,好著急,所以好多都用截屏了,也沒有聽的很細致,好慚愧。
? ? ? ? 這兩天好難受,宿舍和實驗室都空蕩蕩的,一個人待在實驗室學習,其實注意力好難集中,因為真的很難受,但是,一切都會過去的,小楠楠加油(;′⌒`)?
? ? ? ? 現在是21:27,宿管阿姨讓我早點回宿舍,因為外面很黑,也沒有人,她說很危險,我要快速去外面吃個飯然后回宿舍,我心里,好怕喔(;′⌒`)?
? ? ? ? 小楠楠要加油!!!