文章目錄
- JavaWeb 基礎知識 -- 網路編程
- 1.為什么要網路編程?
- 2.什么是網路編程
- 3.網路編程中的基本概念
- (1)發送端和接收端
- (2)請求和回應
- (3)客戶端和服務端
- (4)常見的客戶端服務端模型
- 4.回顯服務器代碼
- 服務器代碼注意事項
- 5.回顯客戶端代碼
- 客戶端代碼注意事項
- 運行展示
JavaWeb 基礎知識 – 網路編程
本文內容大綱

1.為什么要網路編程?
通過代碼來控制,讓兩個主機的行程之間能夠進行資料互動
??我們所說的網路編程,就是通過網路來進行通信,那么具體來說就是網路連接的不同主機,在具體來說連接的是兩個主機之間的行程
比如:
??我使用qq發送了一個訊息,這個訊息就通過我電腦上的qq客戶端行程,先發送給了騰訊的服務器(對應的服務器行程),再由騰訊的服務器行程,把這個訊息轉發給對方電腦的qq行程
??這是我們通過網路編程做的最基礎的一件事情,通過網路編程就可以達到一個天涯若比鄰的效果,就能夠讓互聯網上的很多主機進行配合作業,那么此時我們寫的程式能做的事情就太多太多了…所以網路編程就是一個非常常見的需求場景,
2.什么是網路編程
??網路編程,指網路上的主機,通過不同的行程,以編程的方式實作網路通信(或稱為網路資料傳輸),
??當然,我們只要滿足行程不同就行;所以即便是同一個主機,只要是不同行程,基于網路來傳輸資料,也屬于網路編程,特殊的,對于開發來說,在條件有限的情況下,一般也都是在一個主機中運行多個行程來完成網路編程,
但是,我們一定要明確,我們的目的是提供網路上不同主機,基于網路來傳輸資料資源:
行程A:編程來獲取網路資源
行程B:編程來提供網路資源

那么我們再具體進行網路編程時怎么用程式進行網路編程呢?
??作業系統就把網路編程的一些相關操作封裝起來了,提供了一組API供程式員來使用
這些相關操作都是作業系統提供的功能,訪問網路核心的硬體設備:網卡
??網卡也是歸作業系統來管理的,所以作業系統將網卡做好管理之后,并且給程式員提供一些API,我們直接使用API就可以進行網路通信的操作了,這就是網路編程的基本情況
作業系統提供的網路編程API,我們給起了一個名字,叫 scoket (套接字) API,就是作業系統提供的一組關于網路通信的API介面
socket 的英文原義 :插槽
??由于作業系統提供的socket API 是 C語言風格的介面,所以在Java當中是沒辦法直接使用的, JDK就針對C語言的socket API 進行了封裝, 在標準庫中就有了一組類,這組類就能夠讓我們進行網路編程,但是我們要知道,這組類本質上仍然是呼叫的作業系統提供的scoket API
那么我們這里有一個問題?
Java能夠呼叫C語言的函式嗎?
可以的,不同的語言之間,很多都可以進行相互呼叫,要想跨語言呼叫,核心原理在于了解對應的語言的ABI(二進制編程介面)二進制指令規則等
3.網路編程中的基本概念
(1)發送端和接收端
在一次網路資料傳輸時:
發送端:資料的發送方行程,稱為發送端,發送端主機即網路通信中的源主機,
接收端:資料的接收方行程,稱為接收端,接收端主機即網路通信中的目的主機,
收發端:發送端和接收端兩端,也簡稱為收發端,
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-iTZGQhhU-1642314827172)(24F9E0A8BCD249B8AF662ABD2EF9E4B1)]](https://img.uj5u.com/2022/01/17/296513172133013.png)
注意:發送端和接收端只是相對的,只是一次網路資料傳輸產生資料流向后的概念,
(2)請求和回應
一般來說,獲取一個網路資源,涉及到兩次網路資料傳輸:
第一次:請求資料的發送
第二次:回應資料的發送,
好比在快餐店點一份炒飯:
先要發起請求:點一份炒飯,再有快餐店提供的對應回應:提供一份炒飯

(3)客戶端和服務端
服務端:在常見的網路資料傳輸場景下,把提供服務的一方行程,稱為服務端,可以提供對外服務,
客戶端:獲取服務的一方行程,稱為客戶端,
對于服務來說,一般是提供:
客戶端獲取服務資源
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sC4qWoqx-1642314827173)(576723A77754444EBBBDC4FE53068051)]](https://img.uj5u.com/2022/01/17/296513172133015.png)
好比在銀行辦事:
銀行提供存款服務:用戶(客戶端)保存資源(現金)在銀行(服務端)
銀行提供取款服務:用戶(客戶端)獲取服務端資源(銀行替用戶保管的現金)
(4)常見的客戶端服務端模型
最常見的場景,客戶端是指給用戶使用的程式,服務端是提供用戶服務的程式:
1.客戶端先發送請求到服務端
2.服務端根據請求資料,執行相應的業務處理
3.服務端回傳回應:發送業務處理結果
4.客戶端根據回應資料,展示處理結果(展示獲取的資源,或提示保存資源的處理結果)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-IJGiM5I3-1642314827174)(979D66E20BDF4DAF82F9233102CF82EE)]](https://img.uj5u.com/2022/01/17/296513172133016.png)
這個客戶端服務器模型在網路編程中非常常見,我們必須熟悉程序,
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-2y3z3tF8-1642314827174)(7AE53F1554174A008040FFC3BD508E9F)]](https://img.uj5u.com/2022/01/17/296513172133017.png)
??為了理解這里的每個程序,咱們還是把一家餐館比作是一個服務器
??然后呢,我現在來到這家餐館吃飯,首先我要點菜吧,我說來一個回鍋肉蓋飯,這就是發送請求,然后餐館把菜給端上來相當于把回應給回傳了,而從點餐到上菜之間的這段時間相當于餐館要去做這個飯,要注意,一家餐館好不好不就相取決于做飯的程序嗎,那做的好生意才好,這個做菜的程序就是根據請求計算回應,菜做好了服務員把菜端到我面前這就是回應顯示,
??好了,這就是我們給大家介紹的一些關于網路編程的基礎知識,我們具體寫一個回顯服務器及客戶端的一個應用場景
4.回顯服務器代碼
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpEchoSever {
private DatagramSocket socket = null;
// port 表示埠號
// 服務器在啟動的時候,需要關聯上一個埠號
// 收到資料的時候,就會根據這個埠號決定把資料交給哪個行程
// 雖然此處port寫的型別式 int,但是實際上埠號是一個兩個位元組的無符號整數
// 范圍: 0~65535
public UdpEchoSever(int port) throws SocketException {
this.socket = new DatagramSocket(port);
}
// 通過這個方法來啟動服務器
public void start() throws IOException {
System.out.println("服務器啟動!!");
// 服務器一般都是持續運行的 (7*24)
while (true) {
// 1.讀取請求,當前服務器不知道客戶端啥時候發來請求,receive 方法也會阻塞
// 如果真的有請求過來,此時receive就會回傳
// receive 引數DatagramPacket 是一個輸出型引數,socket 中讀到的資料會設定到這個引數的物件中
// DatagramPacket 在構造的時候需要指定一個緩沖區,通常使用 byte[]
DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
// 這個資料包物件要程式員自定義緩沖區大小
socket.receive(requestPacket);
// 把 reuqestPacket 物件里面的內容給取出來,作為一個字串
String request = new String(requestPacket.getData(),0,requestPacket.getLength());
// 2.根據請求來計算回應
String response = process(request);
// 3.把回應寫回給客戶,這時候也需要構造一個 DatagramPacket
// 此處給DatagramPacket 設定的長度,必須是“位元組的個數”
// 如果直接去response.length() 此處得到的式,字串的長度,也就是“字符的個數”
// 當前的 responsePacket 在構造的時候,還需要指定這個包要發給誰
// 其實發送的目標,就是發送請求的一方
DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
response.getBytes().length,
requestPacket.getSocketAddress()
);
socket.send(responsePacket);
// 4.日志列印
String log = String.format("[%s:%d] req: %s resp: %s",
requestPacket.getAddress().toString(),
requestPacket.getPort(),
request,response);
}
}
// 這里的process 方法負責的功能,就是根據請求來計算回應
// 當前是一個回顯服務器,就是把客戶端的請求直接回傳回去
private String process(String request) {
return request;
}
public static void main(String[] args) throws IOException {
UdpEchoSever udpEchoSever = new UdpEchoSever(9090);
udpEchoSever.start();
}
}
服務器代碼注意事項
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SzPS9tlQ-1642314827175)(135E90F60877425A86AE274B6BD1CC3E)]](https://img.uj5u.com/2022/01/17/296513172133018.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nGOqOtc0-1642314827175)(E10720BB98C44DF3B981B0515E18C291)]](https://img.uj5u.com/2022/01/17/296513172133019.png)
5.回顯客戶端代碼
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class UdpEchoClient {
private DatagramSocket socket = null;
private String severIp;
private int port;
public UdpEchoClient(String severIp,int port) throws SocketException {
this.socket = new DatagramSocket(); // 這里不需要指定埠號,由系統自己分配
this.severIp = severIp;
this.port = port;
}
public void start() throws IOException {
Scanner scanner = new Scanner(System.in);
System.out.println("客戶端啟動!");
while(true){
// 1.從標準輸入讀入一個資料,構造請求
System.out.print("->");
String request = scanner.nextLine();
if(request.equals("exit")){
System.out.println("客戶端下線!");
return;
}
// 2. 將這個字串構造成一個Udp請求,并發送資料
// 這里的 DatagramPacket 中,既要包含具體的資料,又要包含這個資料要發給誰
DatagramPacket requestPacket = new DatagramPacket(
request.getBytes(),
request.getBytes().length,
InetAddress.getByName(severIp), port
);
socket.send(requestPacket);
// 3.嘗試從服務器讀取相應
DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
socket.receive(responsePacket);
String response = new String(responsePacket.getData(),0,responsePacket.getLength());
// 4.列印日志
String log = String.format("req: %s resp: %s",request,response);
System.out.println(log);
}
}
public static void main(String[] args) throws IOException {
// 環回IP : 127.0.0.1 環回Ip 就相當于主機本身
// 當前,客戶端和服務器在同一臺主機上,所以客戶端中寫的服務器 Ip是 127.0.0.1 即可
// 如果在不同主機上,此時就需要寫成對應主機的服務器Ip上
UdpEchoClient udpEchoClient = new UdpEchoClient("127.0.0.1",9090);
udpEchoClient.start();
}
}
客戶端代碼注意事項
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-PS73qked-1642314827176)(E5C6C153FC9C4443A33F8BB993015E07)]](https://img.uj5u.com/2022/01/17/2965131721330110.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uc9UpUTi-1642314827176)(08E978AD287E424A84E167B33BF6EBB0)]](https://img.uj5u.com/2022/01/17/2965131721330111.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-qwGDOTBS-1642314827177)(ED0F8C28DCA74882889E5897A7D14FCC)]](https://img.uj5u.com/2022/01/17/2965131721330112.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-S3Eqt4eC-1642314827177)(507248A58A724C578BE52663FB88E3B7)]](https://img.uj5u.com/2022/01/17/2965131721330113.png)
由于是客戶端先給服務器發請求(客戶端服務器概念的定義決定的)
既然是客戶端先發,客戶端這邊就得先知道服務器的 IP 和 埠號
服務器如果收到了客戶端的資料,服務器也就知道了客戶端的IP 和埠號
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KBdl8ove-1642314827178)(85E74D3839F84E10A9C4D4C03788562C)]](https://img.uj5u.com/2022/01/17/2965131721330114.png)
運行展示
在客戶端依次輸入結果,列印請求和回應,同時服務器列印客戶端主機和埠號及請求回應,客戶端輸入 exit,客戶端下線…

??今天網路編程就講到這里,希望大家多多練習,謝謝大家的閱讀與欣賞…
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/413675.html
標籤:其他
下一篇:jenkins 持續集成
