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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

【Java】网络编程

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

1 通信協議

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

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

三次握手:TCP協議中,在發送數據的準備階段,客戶端與服務器之間的三次交互,以保證連接的可靠。
第一次握手,客戶端向服務器端發出連接請求,等待服務器確認。
第二次握手,服務器端向客戶端回送一個響應,通知客戶端收到了連接請求。
第三次握手,客戶端再次向服務器端發送確認信息,確認連接。整個交互過程如下圖所示。

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

2 網絡編程三要素

協議:計算機網絡通信必須遵守的規則。

IP地址:指互聯網協議地址(Internet Protocol Address),俗稱IP。IP地址用來給一個網絡中的計算機設備做唯一的編號。假如我們把“個人電腦”比作“一臺電話”的話,那么“IP地址”就相當于“電話號碼”。

IP地址分類

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

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

端口號
網絡的通信,本質上是兩個進程(應用程序)的通信。每臺計算機都有很多的進程,那么在網絡通信時,如何區分這些進程呢?如果說IP地址可以唯一標識網絡中的設備,那么端口號就可以唯一標識設備中的進程(應用程序)了。

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

利用協議+ IP地址+ 端口號 三元組合,就可以標識網絡中的進程了,那么進程間的通信就可以利用這個標識與其它進程進行交互。

常用端口號

  • 80端口 網絡端口
  • 數據庫端口 mysql:3306 oracle:1521
  • tomcat端口:8080

3 TCP通信程序

TCP通信能實現兩臺計算機之間的數據交互,通信的兩端要嚴格區分客戶端和服務端

通信步驟

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

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

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

    成員方法

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

    實現步驟

  • 創建客戶端對象Socket,綁定服務器IP地址和端口號
  • 使用socket對象的getOutputStream()獲取網絡字節輸出流對象
  • 使用字節輸出流的write方法發送數據
  • 使用socket對象的getInputStream()獲取網絡字節輸入流對象
  • 使用字節輸入流的read方法讀取數據
  • 釋放資源
  • 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("客戶端:你好服務器".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服務端代碼實現

    構造方法:Socket(int port):創建綁定到特定端口的服務器套接字

    成員方法

    • Socket accept():偵聽并接收到此套接字連接
      實現步驟
  • 創建客戶端對象Socket,綁定服務器IP地址和端口號
  • 使用socket對象的getOutputStream()獲取網絡字節輸出流對象
  • 使用字節輸出流的write方法發送數據
  • 使用socket對象的getInputStream()獲取網絡字節輸入流對象
  • 使用字節輸入流的read方法讀取數據
  • 釋放資源
  • 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("服務端:收到謝謝".getBytes());socket.close();server.close();} }

    3.3 練習1-文件上傳

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

    步驟

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

    客戶端實現

  • 創建本地fis對象讀取本地文件
  • 創建socket對象獲取網絡os對象
  • 使用網絡os對象上傳文件到服務器
  • 使用socket對象獲取網絡is對象
  • 使用網絡is對象讀取服務器回寫的數據
  • 釋放資源
  • //數據源:"a.txt" //目的地服務器"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);}//上傳完文件給服務器寫一個結束標記socket.shutdownOutput();InputStream is = socket.getInputStream();while ((len = is.read(bytes)) != -1){System.out.println(new String(bytes,0,len));}fis.close();//從本地讀取文件 輸出到服務器socket.close();} }

    服務端實現

  • 創建服務器ServerSocket對象,使用accpet方法獲取Socket對象
  • 使用Socket對象的getInputStream獲取網絡字節輸入流對象
  • 判斷上傳的文件夾是否存在,不存在則創建
  • 創建一個本地的字節輸出流fos ,綁定輸出目的地
  • 用網絡is對象讀取客戶端上傳的文件
  • 使用本地字節fos把文件寫道服務器的硬盤上
  • 獲取網絡os對象,使用os對象的write給客戶端發送上傳成功的消息
  • 釋放資源
  • 注意上傳阻塞問題
    fis.read 讀取本地文件 結束標記是讀取到-1
    while循環不會讀取-1 也不會寫給服務器
    read讀不到-1 進入死循環
    解決方法:上傳結束后,寫一個結束標記。使用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("服務端:文件上傳成功".getBytes());socket.close();server.close();} }

    3.4 練習2-文件上傳優化版

  • 自定義文件命名,防止文件同名覆蓋
  • 讓服務器一直處于監聽狀態,客戶端可以多次上傳
  • 使用多線程可以提高文件上傳效率,上傳一次開啟一個線程
  • 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);//優化2:讓服務端一直處于監聽狀態 死循環accept//有一個客戶端上傳就保存一個文件while(true){Socket socket = server.accept();//優化3:使用多線程提高效率 run中實現文件文件上傳 有一個客戶端上傳就開啟一個線程new Thread(new Runnable() {@Overridepublic void run() {try{InputStream is = socket.getInputStream();File file = new File("E:\\upload");if(!file.exists()){file.mkdir();}//優化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("服務端:文件上傳成功".getBytes());socket.close();}catch (IOException e){e.printStackTrace();}}}).start();}} }

    3.5 BS服務器實現

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

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

    總結

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

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。