日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】网络编程

發(fā)布時間:2024/7/5 java 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】网络编程 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1 通信協(xié)議

通信的協(xié)議還是比較復(fù)雜的, java.net 包中包含的類和接口,它們提供低層次的通信細(xì)節(jié)。我們可以直接使用這些類和接口,來專注于網(wǎng)絡(luò)程序開發(fā),而不用考慮通信的細(xì)節(jié)。
java.net 包中提供了兩種常見的網(wǎng)絡(luò)協(xié)議的支持:tcp和udp

TCP:傳輸控制協(xié)議 (Transmission Control Protocol)。TCP協(xié)議是面向連接的通信協(xié)議,即傳輸數(shù)據(jù)之前,在發(fā)送端和接收端建立邏輯連接,然后再傳輸數(shù)據(jù),它提供了兩臺計算機(jī)之間可靠無差錯的數(shù)據(jù)傳輸。

三次握手:TCP協(xié)議中,在發(fā)送數(shù)據(jù)的準(zhǔn)備階段,客戶端與服務(wù)器之間的三次交互,以保證連接的可靠。
第一次握手,客戶端向服務(wù)器端發(fā)出連接請求,等待服務(wù)器確認(rèn)。
第二次握手,服務(wù)器端向客戶端回送一個響應(yīng),通知客戶端收到了連接請求。
第三次握手,客戶端再次向服務(wù)器端發(fā)送確認(rèn)信息,確認(rèn)連接。整個交互過程如下圖所示。

UDP:用戶數(shù)據(jù)報協(xié)議(User Datagram Protocol)。UDP協(xié)議是一個面向無連接的協(xié)議。傳輸數(shù)據(jù)時,不需要建立連接,不管對方端服務(wù)是否啟動,直接將數(shù)據(jù)、數(shù)據(jù)源和目的地都封裝在數(shù)據(jù)包中,直接發(fā)送。每個數(shù)據(jù)包的大小限制在64k以內(nèi)。它是不可靠協(xié)議,因為無連接,所以傳輸速度快,但是容易丟失數(shù)據(jù)。日常應(yīng)用中,例如視頻會議、QQ聊天等。耗資小效率高,容易丟數(shù)據(jù)

2 網(wǎng)絡(luò)編程三要素

協(xié)議:計算機(jī)網(wǎng)絡(luò)通信必須遵守的規(guī)則。

IP地址:指互聯(lián)網(wǎng)協(xié)議地址(Internet Protocol Address),俗稱IP。IP地址用來給一個網(wǎng)絡(luò)中的計算機(jī)設(shè)備做唯一的編號。假如我們把“個人電腦”比作“一臺電話”的話,那么“IP地址”就相當(dāng)于“電話號碼”。

IP地址分類

  • IPv4:是一個32位的二進(jìn)制數(shù),通常被分為4個字節(jié),表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之間的十進(jìn)制整數(shù),那么最多可以表示42億個。
  • IPv6:由于互聯(lián)網(wǎng)的蓬勃發(fā)展,IP地址的需求量愈來愈大,但是網(wǎng)絡(luò)地址資源有限,使得IP的分配越發(fā)緊張。有資料顯示,全球IPv4地址在2011年2月分配完畢。為了擴(kuò)大地址空間,擬通過IPv6重新定義地址空間,采用128位地址長度,每16個字節(jié)一組,分成8組十六進(jìn)制數(shù),表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789 ,號稱可以為全世界的每一粒沙子編上一個網(wǎng)址,這樣就解決了網(wǎng)絡(luò)地址資源數(shù)量不夠的問題。

常用命令
查看本機(jī)IP地址,在控制臺輸入:ipconfig
檢查網(wǎng)絡(luò)是否連通,在控制臺輸入:ping ip地址
特殊的IP地址:本機(jī)IP地址: 127.0.0.1 、localhost 。

端口號
網(wǎng)絡(luò)的通信,本質(zhì)上是兩個進(jìn)程(應(yīng)用程序)的通信。每臺計算機(jī)都有很多的進(jìn)程,那么在網(wǎng)絡(luò)通信時,如何區(qū)分這些進(jìn)程呢?如果說IP地址可以唯一標(biāo)識網(wǎng)絡(luò)中的設(shè)備,那么端口號就可以唯一標(biāo)識設(shè)備中的進(jìn)程(應(yīng)用程序)了。

端口號:用兩個字節(jié)表示的整數(shù),它的取值范圍是0~65535。其中,0~1023之間的端口號用于一些知名的網(wǎng)絡(luò)服務(wù)和應(yīng)用,普通的應(yīng)用程序需要使用1024以上的端口號。如果端口號被另外一個服務(wù)或應(yīng)用所占用,會導(dǎo)致當(dāng)前程序啟動失敗。

利用協(xié)議+ IP地址+ 端口號 三元組合,就可以標(biāo)識網(wǎng)絡(luò)中的進(jìn)程了,那么進(jìn)程間的通信就可以利用這個標(biāo)識與其它進(jìn)程進(jìn)行交互。

常用端口號

  • 80端口 網(wǎng)絡(luò)端口
  • 數(shù)據(jù)庫端口 mysql:3306 oracle:1521
  • tomcat端口:8080

3 TCP通信程序

TCP通信能實現(xiàn)兩臺計算機(jī)之間的數(shù)據(jù)交互,通信的兩端要嚴(yán)格區(qū)分客戶端和服務(wù)端

通信步驟

  • 服務(wù)器端先啟動
  • 客戶端請求服務(wù)器端
  • 客戶端服務(wù)端經(jīng)過三次握手建立邏輯連接
  • 連接中包含一個IO對象,使用IO流對象進(jìn)行通信,IO流對象是字節(jié)流對象。
  • 服務(wù)端要做的事

  • 服務(wù)端需要知道自己在和哪個客戶端交互,通過accept方法獲取到請求的客戶端對象
  • 多個客戶端和服務(wù)端交互需要使用多個IO流對象。服務(wù)端沒有IO流,它可以獲取到請求的客戶端對象socket使用每個客戶端的socket中提供的IO流和客戶端進(jìn)行交互。使用輸入流讀數(shù)據(jù),使用輸出流發(fā)數(shù)據(jù)。
  • 3.1 TCP客戶端代碼實現(xiàn)

    構(gòu)造方法:Socket(String host, int port)

    成員方法

    • OutputStream getOutputStream():返回輸出流
    • InputStream getInputStream():返回輸入流
    • void close():關(guān)閉套接字

    實現(xiàn)步驟

  • 創(chuàng)建客戶端對象Socket,綁定服務(wù)器IP地址和端口號
  • 使用socket對象的getOutputStream()獲取網(wǎng)絡(luò)字節(jié)輸出流對象
  • 使用字節(jié)輸出流的write方法發(fā)送數(shù)據(jù)
  • 使用socket對象的getInputStream()獲取網(wǎng)絡(luò)字節(jié)輸入流對象
  • 使用字節(jié)輸入流的read方法讀取數(shù)據(jù)
  • 釋放資源
  • public class TCPClient {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1",8888);OutputStream os = socket.getOutputStream();os.write("客戶端:你好服務(wù)器".getBytes());InputStream is = socket.getInputStream();byte[] bytes = new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes,0,len));socket.close();} }

    3.2 TCP服務(wù)端代碼實現(xiàn)

    構(gòu)造方法:Socket(int port):創(chuàng)建綁定到特定端口的服務(wù)器套接字

    成員方法

    • Socket accept():偵聽并接收到此套接字連接
      實現(xiàn)步驟
  • 創(chuàng)建客戶端對象Socket,綁定服務(wù)器IP地址和端口號
  • 使用socket對象的getOutputStream()獲取網(wǎng)絡(luò)字節(jié)輸出流對象
  • 使用字節(jié)輸出流的write方法發(fā)送數(shù)據(jù)
  • 使用socket對象的getInputStream()獲取網(wǎng)絡(luò)字節(jié)輸入流對象
  • 使用字節(jié)輸入流的read方法讀取數(shù)據(jù)
  • 釋放資源
  • public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);Socket socket = server.accept();InputStream is = socket.getInputStream();byte[] bytes= new byte[1024];int len = is.read(bytes);System.out.println(new String(bytes, 0, len));OutputStream os = socket.getOutputStream();os.write("服務(wù)端:收到謝謝".getBytes());socket.close();server.close();} }

    3.3 練習(xí)1-文件上傳

    原理:客戶端讀取本地的文件,把文件上傳到服務(wù)器,服務(wù)器把上傳的文件保存到服務(wù)器的硬盤上。

    步驟

  • 客戶端使用本地的字節(jié)輸入流,讀取要上傳的文件
  • 客戶端使用網(wǎng)絡(luò)字節(jié)輸出流,把讀取到的文件上傳到服務(wù)器
  • 服務(wù)器使用網(wǎng)絡(luò)字節(jié)輸入流,讀取客戶端上傳的文件
  • 服務(wù)端使用本地的字節(jié)輸出流,把讀取到的文件保存到服務(wù)器的硬盤上
  • 服務(wù)器使用網(wǎng)絡(luò)字節(jié)輸出流,給客戶端回寫一個上傳成功
  • 客戶端使用網(wǎng)絡(luò)字節(jié)輸入流,讀取客戶端回寫的消息
  • 本地硬盤讀寫用本地字節(jié)流,CS間通信用網(wǎng)絡(luò)字節(jié)流

    客戶端實現(xiàn)

  • 創(chuàng)建本地fis對象讀取本地文件
  • 創(chuàng)建socket對象獲取網(wǎng)絡(luò)os對象
  • 使用網(wǎng)絡(luò)os對象上傳文件到服務(wù)器
  • 使用socket對象獲取網(wǎng)絡(luò)is對象
  • 使用網(wǎng)絡(luò)is對象讀取服務(wù)器回寫的數(shù)據(jù)
  • 釋放資源
  • //數(shù)據(jù)源:"a.txt" //目的地服務(wù)器"D:\\upload\\" public class TCPClient {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("a.txt");Socket socket = new Socket("127.0.0.1",8888);OutputStream os = socket.getOutputStream();int len = 0;byte[] bytes = new byte[1024];while((len = fis.read(bytes)) != -1){os.write(bytes,0,len);}//上傳完文件給服務(wù)器寫一個結(jié)束標(biāo)記socket.shutdownOutput();InputStream is = socket.getInputStream();while ((len = is.read(bytes)) != -1){System.out.println(new String(bytes,0,len));}fis.close();//從本地讀取文件 輸出到服務(wù)器socket.close();} }

    服務(wù)端實現(xiàn)

  • 創(chuàng)建服務(wù)器ServerSocket對象,使用accpet方法獲取Socket對象
  • 使用Socket對象的getInputStream獲取網(wǎng)絡(luò)字節(jié)輸入流對象
  • 判斷上傳的文件夾是否存在,不存在則創(chuàng)建
  • 創(chuàng)建一個本地的字節(jié)輸出流fos ,綁定輸出目的地
  • 用網(wǎng)絡(luò)is對象讀取客戶端上傳的文件
  • 使用本地字節(jié)fos把文件寫道服務(wù)器的硬盤上
  • 獲取網(wǎng)絡(luò)os對象,使用os對象的write給客戶端發(fā)送上傳成功的消息
  • 釋放資源
  • 注意上傳阻塞問題
    fis.read 讀取本地文件 結(jié)束標(biāo)記是讀取到-1
    while循環(huán)不會讀取-1 也不會寫給服務(wù)器
    read讀不到-1 進(jìn)入死循環(huán)
    解決方法:上傳結(jié)束后,寫一個結(jié)束標(biāo)記。使用socket.shutdown()

    public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);Socket socket = server.accept();InputStream is = socket.getInputStream();File file = new File("E:\\upload");if(!file.exists()){file.mkdir();}FileOutputStream fos = new FileOutputStream(file+"\\a.txt");byte[] bytes= new byte[1024];int len = 0;while((len = is.read(bytes))!= -1){fos.write(bytes,0,len);}OutputStream os = socket.getOutputStream();os.write("服務(wù)端:文件上傳成功".getBytes());socket.close();server.close();} }

    3.4 練習(xí)2-文件上傳優(yōu)化版

  • 自定義文件命名,防止文件同名覆蓋
  • 讓服務(wù)器一直處于監(jiān)聽狀態(tài),客戶端可以多次上傳
  • 使用多線程可以提高文件上傳效率,上傳一次開啟一個線程
  • package tcp;import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.Random;public class TCPServer {public static void main(String[] args) throws IOException {ServerSocket server = new ServerSocket(8888);//優(yōu)化2:讓服務(wù)端一直處于監(jiān)聽狀態(tài) 死循環(huán)accept//有一個客戶端上傳就保存一個文件while(true){Socket socket = server.accept();//優(yōu)化3:使用多線程提高效率 run中實現(xiàn)文件文件上傳 有一個客戶端上傳就開啟一個線程new Thread(new Runnable() {@Overridepublic void run() {try{InputStream is = socket.getInputStream();File file = new File("E:\\upload");if(!file.exists()){file.mkdir();}//優(yōu)化1:自定義文件名String filename = "zxc"+System.currentTimeMillis()+new Random().nextInt(9999)+".txt";FileOutputStream fos = new FileOutputStream(file+"\\"+filename);byte[] bytes= new byte[1024];int len = 0;while((len = is.read(bytes))!= -1){fos.write(bytes,0,len);}OutputStream os = socket.getOutputStream();os.write("服務(wù)端:文件上傳成功".getBytes());socket.close();}catch (IOException e){e.printStackTrace();}}}).start();}} }

    3.5 BS服務(wù)器實現(xiàn)

    使用FileInputStream創(chuàng)建對象的時候遇到了問題,相對路徑訪問不了,這個問題暫時還不知道怎么解決,所以強(qiáng)行把父路徑加上了,訪問絕對路徑就沒問題。

    import java.io.*; import java.net.ServerSocket; import java.net.Socket;/*創(chuàng)建BS版本TCP服務(wù)器*/ public class TCPServerThread {public static void main(String[] args) throws IOException {//創(chuàng)建一個服務(wù)器ServerSocket,和系統(tǒng)要指定的端口號ServerSocket server = new ServerSocket(8080);/*瀏覽器解析服務(wù)器回寫的html頁面,頁面中如果有圖片,那么瀏覽器就會單獨的開啟一個線程,讀取服務(wù)器的圖片我們就的讓服務(wù)器一直處于監(jiān)聽狀態(tài),客戶端請求一次,服務(wù)器就回寫一次*/while(true){//使用accept方法獲取到請求的客戶端對象(瀏覽器)Socket socket = server.accept();new Thread(new Runnable() {@Overridepublic void run() {try {//使用Socket對象中的方法getInputStream,獲取到網(wǎng)絡(luò)字節(jié)輸入流InputStream對象InputStream is = socket.getInputStream();//把is網(wǎng)絡(luò)字節(jié)輸入流對象,轉(zhuǎn)換為字符緩沖輸入流BufferedReader br = new BufferedReader(new InputStreamReader(is));//把客戶端請求信息的第一行讀取出來 GET /11_Net/web/index.html HTTP/1.1String line = br.readLine();System.out.println(line);//把讀取的信息進(jìn)行切割,只要中間部分 /11_Net/web/index.htmlString[] arr = line.split(" ");//把路徑前邊的/去掉,進(jìn)行截取 11_Net/web/index.htmlString htmlpath = arr[1].substring(1);//使用FileInputStream創(chuàng)建對象的時候遇到了問題//相對路徑訪問不了 不知道怎么解決//所以強(qiáng)行把父路徑加上了//訪問絕對路徑就沒問題File file = new File("").getAbsoluteFile();htmlpath = file.getParent() + "\\" + htmlpath;//創(chuàng)建一個本地字節(jié)輸入流,構(gòu)造方法中綁定要讀取的html路徑FileInputStream fis = new FileInputStream(htmlpath);//使用Socket中的方法getOutputStream獲取網(wǎng)絡(luò)字節(jié)輸出流OutputStream對象OutputStream os = socket.getOutputStream();// 寫入HTTP協(xié)議響應(yīng)頭,固定寫法os.write("HTTP/1.1 200 OK\r\n".getBytes());os.write("Content-Type:text/html\r\n".getBytes());// 必須要寫入空行,否則瀏覽器不解析os.write("\r\n".getBytes());//一讀一寫復(fù)制文件,把服務(wù)讀取的html文件回寫到客戶端int len = 0;byte[] bytes = new byte[1024];while((len = fis.read(bytes))!=-1){os.write(bytes,0,len);}//釋放資源fis.close();socket.close();}catch (IOException e){e.printStackTrace();}}}).start();}//server.close();} }

    總結(jié)

    以上是生活随笔為你收集整理的【Java】网络编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。