前言
一個(gè)網(wǎng)絡(luò)請(qǐng)求、服務(wù)之間的調(diào)用都需要進(jìn)行網(wǎng)絡(luò)通訊,在日常開(kāi)發(fā)時(shí)我們可能并不會(huì)關(guān)心我們的服務(wù)端是怎么接收到請(qǐng)求的、調(diào)用別的服務(wù)是怎么調(diào)用的,都是直接使用現(xiàn)成的框架或工具,比如,Tomcat、Dubbo、OkHttp等提供網(wǎng)絡(luò)服務(wù)的框架。作為程序員,我們還是要知其然知其所以然。本文將介紹在 Java 中如何進(jìn)行網(wǎng)絡(luò)編程以及網(wǎng)絡(luò)編程的基礎(chǔ)知識(shí)。
什么是網(wǎng)絡(luò)編程
網(wǎng)絡(luò)編程是指利用網(wǎng)絡(luò)協(xié)議和技術(shù)實(shí)現(xiàn)計(jì)算機(jī)應(yīng)用程序之間的通信、數(shù)據(jù)傳輸、交換,如TCP/IP協(xié)議、HTTP協(xié)議、Socket編程等,像 Java、C、C++、Python 這些語(yǔ)言都提供了網(wǎng)絡(luò)編程的API和庫(kù)函數(shù),可以便捷地進(jìn)行網(wǎng)絡(luò)應(yīng)用程序的開(kāi)發(fā)。
網(wǎng)絡(luò)編程基礎(chǔ)知識(shí)
網(wǎng)絡(luò)通訊流程
網(wǎng)絡(luò)通訊過(guò)程通常包括以下幾個(gè)步驟:
-
建立連接:通訊雙方在網(wǎng)絡(luò)中建立連接,即在物理層和鏈路層上進(jìn)行握手,確認(rèn)通訊協(xié)議和傳輸參數(shù)。
-
數(shù)據(jù)傳輸:建立連接后,數(shù)據(jù)可以在通訊雙方之間進(jìn)行傳輸。數(shù)據(jù)傳輸過(guò)程中,需要進(jìn)行分段、封裝、逐層封裝、加密和校驗(yàn)等。
-
數(shù)據(jù)接收:數(shù)據(jù)接收方需要先解析、解封裝和驗(yàn)證傳輸數(shù)據(jù)的正確性,然后對(duì)數(shù)據(jù)進(jìn)行處理,包括存儲(chǔ)和響應(yīng)等。
-
斷開(kāi)連接:在數(shù)據(jù)傳輸完成后,通訊雙方需要在網(wǎng)絡(luò)中斷開(kāi)連接,釋放資源,并進(jìn)行必要的后續(xù)操作。
長(zhǎng)連接和短連接
長(zhǎng)連接和短連接是指客戶端和服務(wù)器端網(wǎng)絡(luò)連接的不同方式。
長(zhǎng)連接指在客戶端和服務(wù)器端之間建立一條長(zhǎng)期保持的連接。一旦建立連接后,客戶端和服務(wù)器端就可以持續(xù)交換數(shù)據(jù),而不需要每次發(fā)送請(qǐng)求都重新建立連接。長(zhǎng)連接通常用于需要頻繁交換數(shù)據(jù)的場(chǎng)合,如在線游戲、聊天室和實(shí)時(shí)視頻等。
短連接指客戶端和服務(wù)器端之間在完成一次請(qǐng)求后立即斷開(kāi)連接。每次發(fā)送請(qǐng)求都需要重新建立連接。短連接通常用于只需要偶爾交換數(shù)據(jù)的場(chǎng)合,如HTTP請(qǐng)求、電子郵件和瀏覽網(wǎng)頁(yè)等。
長(zhǎng)連接可以減少連接建立的開(kāi)銷(xiāo),提高數(shù)據(jù)傳輸效率,但可能會(huì)浪費(fèi)一定的網(wǎng)絡(luò)資源。短連接則可以節(jié)省網(wǎng)絡(luò)資源,但會(huì)增加連接建立的開(kāi)銷(xiāo)和數(shù)據(jù)傳輸?shù)难舆t。
Socket
所謂 Socket (套接字),就是對(duì)網(wǎng)絡(luò)中不同主機(jī)上的應(yīng)用進(jìn)程之間進(jìn)行雙向通信的抽象。一個(gè)套接字就是網(wǎng)絡(luò)上進(jìn)程通信的一端,提供了應(yīng)用層進(jìn)程利用網(wǎng)絡(luò)協(xié)議交換數(shù)據(jù)的機(jī)制。從所處的地位來(lái)講,套接字上聯(lián)應(yīng)用進(jìn)程,下聯(lián)網(wǎng)絡(luò)協(xié)議棧,是應(yīng)用程序通過(guò)網(wǎng)絡(luò)協(xié)議進(jìn)行通信的接口,是應(yīng)用程序與網(wǎng)絡(luò)協(xié)議棧進(jìn)行交互的接口。
Socket 接口把復(fù)雜的 TCP/IP 協(xié)議族隱藏在后面,對(duì)開(kāi)發(fā)人員來(lái)講,通過(guò)調(diào)用一組接口就可完成網(wǎng)絡(luò)通信。
Java 網(wǎng)絡(luò)編程
Java提供了一個(gè)強(qiáng)大的網(wǎng)絡(luò)編程模型和豐富的API來(lái)實(shí)現(xiàn)網(wǎng)絡(luò)應(yīng)用程序,主要基于Socket編程,提供了 ServerSocket 和 Socket 兩種Socket,分別用于實(shí)現(xiàn)服務(wù)器端和客戶端。ServerSocket負(fù)責(zé)綁定IP地址,監(jiān)聽(tīng)端口,Socket負(fù)責(zé)發(fā)起連接操作。連接成功后,雙方通過(guò)輸入和輸出流進(jìn)行同步阻塞式通信。代碼如下:
public class Server {
public static void main(String[] args) throws IOException {
/*服務(wù)器必備*/
ServerSocket serverSocket = new ServerSocket();
/*綁定監(jiān)聽(tīng)端口*/
serverSocket.bind(new InetSocketAddress(10001));
System.out.println("Server start.......");
while(true){
//serverSocket.accept()時(shí)阻塞,直到接收到客戶端的請(qǐng)求
new Thread(new ServerTask(serverSocket.accept())).start();
}
}
private static class ServerTask implements Runnable{
private Socket socket = null;
public ServerTask(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
/*socket.getInputStream() 為客戶端的輸出流*/
try(
ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream())
){
String msg = inputStream.readUTF();
System.out.println("Accept clinet message:"+msg);
/*服務(wù)器的響應(yīng)*/
outputStream.writeUTF("Hello,"+msg);
outputStream.flush();
}catch (Exception e){
e.printStackTrace();
}
finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public class Client {
public static void main(String[] args) throws IOException {
Socket socket = null;
//與服務(wù)端通信的輸入輸出流
ObjectOutputStream output = null;
ObjectInputStream input = null;
//服務(wù)器的通信地址
InetSocketAddress addr = new InetSocketAddress("127.0.0.1",10001);
try{
socket = new Socket();
/*連接服務(wù)器*/
socket.connect(addr);
output = new ObjectOutputStream(socket.getOutputStream());
input = new ObjectInputStream(socket.getInputStream());
/*向服務(wù)器輸出請(qǐng)求*/
output.writeUTF("i‘m Client");
output.flush();
//接收服務(wù)器的輸出
System.out.println(input.readUTF());
}finally{
if (socket!=null) socket.close();
if (output!=null) output.close();
if (input!=null) input.close();
}
}
}
以上代碼是傳統(tǒng)BIO通信模型:采用 BIO 通信模型的服務(wù)端,通常由一個(gè)獨(dú)立的 Acceptor 線程負(fù)責(zé)監(jiān)聽(tīng)客戶端的連接、處理、響應(yīng),典型的一請(qǐng)求一應(yīng)答模型。該模型最大的問(wèn)題就是缺乏彈性伸縮能力,當(dāng)客戶端并發(fā)訪問(wèn)量增加后,線程數(shù)量快速膨脹,系統(tǒng)的性能將急劇下降,隨著訪問(wèn)量的繼續(xù)增大,系統(tǒng)最終就會(huì)宕機(jī)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-610991.html
總結(jié)
對(duì)網(wǎng)絡(luò)編程有所了解后,也就大概知道Tomcat、Dubbo這樣的框架最基本的實(shí)現(xiàn)原理,拿 Tomcat 舉例,無(wú)非就是作為服務(wù)端監(jiān)聽(tīng)一個(gè)端口,當(dāng)這個(gè)端口有請(qǐng)求時(shí)對(duì)參數(shù)進(jìn)行接收處理,處理后響應(yīng)給客戶端。當(dāng)然這種成熟的框架是非常復(fù)雜的,有很多細(xì)節(jié)要考慮,比如數(shù)據(jù)的序列化問(wèn)題、性能問(wèn)題、安全問(wèn)題、穩(wěn)定性、擴(kuò)展性、可靠性等。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-610991.html
到了這里,關(guān)于Java 網(wǎng)絡(luò)編程基礎(chǔ)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!