JAVA學習線路:day14-網路程式設計
阿新 • • 發佈:2020-11-04
>**心得:**
> 我是一名正在自學的java的即將畢業的大學生
> 總結筆記是為了讓自己更好的理解和加深印象。可能不是那麼美觀,自己可以看懂就好
> *所有的文件和原始碼都開源在**GitHub**: [**https://github.com/kun213/JavaNotes**](https://github.com/kun213/JavaNotes/)上了*。希望我們可以一起加油,一起學習,一起交流
## day14 【網路程式設計】
@[toc](今日學習內容-2020.10.16)
## 一、網路程式設計入門
### 1.1 可以說出軟體的結構
**C/S結構** :全稱為Client/Server結構,是指客戶端和伺服器結構。常見程式有QQ、迅雷等軟體。
**B/S結構** :全稱為Browser/Server結構,是指瀏覽器和伺服器結構。常見瀏覽器有谷歌、火狐等。
### 1.2 可以說出UDP和TCP協議特點
- **TCP**:傳輸控制協議 (Transmission Control Protocol)。TCP協議是**面向連線**的通訊協議,即傳輸資料之前,在傳送端和接收端建立邏輯連線,然後再傳輸資料,它提供了兩臺計算機之間可靠無差錯的資料傳輸。
- 三次握手:TCP協議中,在傳送資料的準備階段,客戶端與伺服器之間的三次互動,以保證連線的可靠。
- 第一次握手,客戶端向伺服器端發出連線請求,等待伺服器確認。
- 第二次握手,伺服器端向客戶端回送一個響應,通知客戶端收到了連線請求。
- 第三次握手,客戶端再次向伺服器端傳送確認資訊,確認連線。整個互動過程如下圖所示
![](https://img-blog.csdnimg.cn/img_convert/6e82960b9e2824bc62c8931f70f96e27.png)
完成三次握手,連線建立後,客戶端和伺服器就可以開始進行資料傳輸了。由於這種面向連線的特性,TCP協議可以保證傳輸資料的安全,所以應用十分廣泛,例如下載檔案、瀏覽網頁等。
- **UDP**:使用者資料報協議(User Datagram Protocol)。UDP協議是一個**面向無連線**的協議。傳輸資料時,不需要建立連線,不管對方端服務是否啟動,直接將資料、資料來源和目的地都封裝在資料包中,直接傳送。每個資料包的大小限制在64k以內。它是不可靠協議,因為無連線,所以傳輸速度快,但是容易丟失資料。日常應用中,例如視訊會議、QQ聊天等。
每次傳送的資料最大為64kb。
## 二、TCP通訊協議
### 2.1 可以說出TCP協議下兩個常用類名稱
**在Java中,提供了兩個類用於實現TCP通訊程式:**
- 客戶端:`java.net.Socket` 類表示。建立`Socket`物件,向服務端發出連線請求,服務端響應請求,兩者建立連線開始通訊。
- 服務端:`java.net.ServerSocket` 類表示。建立`ServerSocket`物件,相當於開啟一個服務,並等待客戶端的連線。
### 2.2 如何編寫TCP協議下字串資料傳輸程式
實現TCP通訊的客戶端程式:
```java
/**
* 實現TCP通訊的客戶端程式
*
* java.net.Socket 實現客戶端的套接字物件,連線物件
*
* 需求: 客戶端程式和伺服器程式實現資料交換
*
* 實現步驟:
* 1: 建立Socket物件 (主動連線伺服器)
* Socket(String host, int port)
*
* 2: OutputStream getOutputStream()
* 返回套接字中的位元組輸出流
* 方法write寫入資料, 寫到伺服器
*
* 3: InputStream getInputStream()
* 返回套接字中的位元組輸入流
* 方法read讀取資料,讀取的是伺服器發回來的資料
*
* 4: 釋放資源
*/
public class TCPClient {
public static void main(String[] args)throws IOException {
//建立Socket物件 (主動連線伺服器)
Socket socket = new Socket("127.0.0.1",9000);
//OutputStream getOutputStream()
OutputStream out = socket.getOutputStream();
//位元組流的方法寫資料
out.write("你好伺服器".getBytes());//沒有寫到檔案中,寫到了伺服器中
InputStream in = socket.getInputStream();//獲取位元組輸入流
byte[] bytes = new byte[1024];
int len = in.read(bytes);//客戶端輸入流,讀取到伺服器發回來的資料
System.out.println(new String(bytes,0,len));
//釋放資源
//out.close();
socket.close();
}
}
```
實現TCP通訊的伺服器程式:
```java
/**
* 實現TCP通訊的伺服器程式
* 192.168.27.95
* java.net.ServerSocket 實現TCP協議中的伺服器套接字物件
*
* 實現TCP伺服器程式步驟:
* 1: 建立ServerSocket物件
* ServerSocket(int port) 埠號
*
* 2: 等待客戶端的連線,如果沒有客戶端連線,永遠等待
* ServerSocket類方法 accept()同意
* 方法 accept()返回值是 Socket物件 (客戶端的連線物件,包含客戶端的IP)
*
* 3: Socket物件中獲取到位元組輸出流
* OutputStream getOutputStream()
* 方法write寫資料,寫到客戶端
*
* 4: Socket物件中獲取到位元組輸入流
* InputStream getInputStream()
* 方法read讀取資料,讀取的是客戶端發來資料
*
* 5: 釋放資源
*/
public class TCPServer {
public static void main(String[] args)throws IOException {
//建立ServerSocket物件
ServerSocket server = new ServerSocket(9000);
//ServerSocket類方法 accept()同意
Socket socket = server.accept();
//System.out.println(socket);
//使用客戶端連接獲取物件,輸入流
InputStream in = socket.getInputStream();
//in輸入流的方法read()讀取客戶端發來資料
byte[] bytes = new byte[1024];
//len返回的是讀取到的位元組個數
int len = in.read(bytes);
System.out.println(new String(bytes,0,len));
//Socket客戶端物件,獲取位元組輸出流
OutputStream out = socket.getOutputStream();
out.write("收到!".getBytes());//伺服器輸出流,寫回客戶端
//釋放資源
socket.close();
server.close();
}
}
```
### 2.3 理解TCP協議下檔案上傳案例
![](https://img-blog.csdnimg.cn/img_convert/baf7cd559981cfdca3bcfca342ac4c46.png)
實現圖片上傳客戶端:
```java
/**
* 實現TCP圖片上傳客戶端
* 實現步驟:
* 1: 建立Socket物件,連線伺服器
* 2: FileInputStream讀取 mm.jpg 位元組陣列
* 3: Socket物件獲取位元組輸出流
* 位元組陣列,交給輸出流,寫到伺服器
* 4: Socket物件獲取位元組輸入流
* 全部的圖片傳送完畢
* 輸入流,讀取伺服器回來的提示資訊 "上傳成功"
*
* 客戶端方法Socket: shutdownOutput() 終止連線物件的輸出流 ,
* 同時跟上TCP終止序列
* 5: 釋放資源
*/
public class TCPClient {
public static void main(String[] args) throws IOException{
//1: 建立Socket物件,連線伺服器
Socket socket = new Socket("127.0.0.1",9000);
//2: 自己的位元組輸入流,讀取圖片mm.jpg
FileInputStream fis = new FileInputStream("e:/msh.jpg");
//3: Socket物件獲取位元組輸出流
OutputStream out = socket.getOutputStream();//任何資料,寫向伺服器
byte[] bytes = new byte[1024];
int len = 0;
//fis讀取檔案末尾,JVM返回read() -1
while ((len = fis.read(bytes))!=-1){
out.write(bytes,0,len);
}
//告訴伺服器,沒資料了,別讀,伺服器傳送TCP的終止符
socket.shutdownOutput();
//4:Socket物件獲取位元組輸入流
InputStream in = socket.getInputStream();//輸入流,讀取伺服器回來的資料
len = in.read(bytes);
System.out.println("伺服器提示::"+new String(bytes,0,len));
socket.close();
}
}
```
實現圖片上傳伺服器端:
```java
/**
* 實現圖片上傳伺服器端
* 實現步驟:
* 1: 建立物件ServerSocket 繫結埠
* 2: Socket accept()方法等待客戶端連線
* 3: Socket物件,獲取位元組輸入流,讀取客戶端發來圖片的位元組
* 4: 建立位元組輸出流,讀取到圖片,寫到 e:/upload
* 5: Socket物件,獲取位元組輸出流,"上傳成功"寫回客戶端
*
* bug:
* 1: 演示了2次,為什麼資料夾中只有一個檔案,同名覆蓋
* a: 1.jpg
* b: 1.jpg
*
* 2: 客戶端收不到伺服器的上傳成功
//告訴伺服器,沒資料了,別讀,伺服器傳送TCP的終止符
*/
public class TCPServer {
public static void main(String[] args) throws IOException{
//1: 建立物件ServerSocket 繫結埠
ServerSocket server = new ServerSocket(9000);
// 2: Socket accept()方法等待客戶端連線
Socket socket = server.accept();
//3: Socket物件,獲取位元組輸入流,讀取客戶端發來圖片的位元組
InputStream in = socket.getInputStream();
//4: 建立位元組輸出流,讀取到圖片,寫到 e:/upload
//上傳的檔案,重新命名,獲取當前日期 轉換成字串
String filename = new SimpleDateFormat("yyyyMMddHHmmssssss").format(Calendar.getInstance().getTime())+".jpg";
FileOutputStream fos = new FileOutputStream("e:/upload/"+filename);
byte[] bytes = new byte[1024];
int len = 0;
//read()讀取是客戶端寫來的圖片!!
while ( (len = in.read(bytes))!=-1){
fos.write(bytes,0,len);
}
//5: Socket物件,獲取位元組輸出流,"上傳成功"寫回客戶端
OutputStream out= socket.getOutputStream();
out.write("上傳成功!".getBytes());
socket.close();
server.close();
}
}
```
------
***這是我的公眾號,希望大家可以關注,讓我們一起做最好的自我。
我也會把我自學視訊分享在上面,供大家一起學習。***
![CodeBull](https://img-blog.csdnimg.cn/20201008185633816.jpg#pic_center)