Java 全面掌握網(wǎng)絡(luò)編程篇
計算機網(wǎng)絡(luò)
是指將地理位置不同的具有獨立功能的多臺計算機及其外部設(shè)備,通過通信線路連接起來,在網(wǎng)絡(luò)操作系統(tǒng),網(wǎng)絡(luò)管理軟件及網(wǎng)絡(luò)通信協(xié)議的管理和協(xié)調(diào)下,實現(xiàn)資源共享和信息傳遞的計算機系統(tǒng)。包括局域網(wǎng)(intranet)和廣域網(wǎng)(internet)
網(wǎng)絡(luò)模型
網(wǎng)絡(luò)模型一般是指
○ OSI(Open System Interconnection開放系統(tǒng)互連)參考模型
○ TCP/IP參考模型
網(wǎng)絡(luò)編程 就是用來實現(xiàn)網(wǎng)絡(luò)互聯(lián)的不同計算機上運行的程序間可以進行數(shù)據(jù)交換。
計算機網(wǎng)絡(luò)之間以何種規(guī)則進行通信,就是網(wǎng)絡(luò)模型研究問題
客戶機服務(wù)器模式(Client/Server)
●為了實現(xiàn)兩臺計算機的通信,必須要用一個網(wǎng)絡(luò)線路連接兩臺計算機。
● 服務(wù)器(Server)是指提供信息的計算機或程序
●客戶機(Client)是指請求信息的計算機或程序
●網(wǎng)絡(luò)用于連接服務(wù)器與客戶機,實現(xiàn)兩者相互通信。
TCP/IP的概念和實現(xiàn)
TCP/IP:Transmission Control Protocol/Internet Protocol的簡寫。TCP 是傳輸控制協(xié)議的縮寫,它保障了兩個應(yīng)用程序之間的可靠通信。通常用于互聯(lián)網(wǎng)協(xié)議,被稱 TCP / IP。
TCP三次握手(Three-way handshake)
所謂的“三次握手”即對每次發(fā)送的數(shù)據(jù)量是怎樣跟蹤進行協(xié)商使數(shù)據(jù)段的發(fā)送和接收同步,根據(jù)所接收到的數(shù)據(jù)量而確定的數(shù)據(jù)確認數(shù)及數(shù)據(jù)發(fā)送、接收完畢后何時撤消聯(lián)系,并建立連接。
❤ 第一次握手:建立連接時,客戶端發(fā)送syn包(syn=j)到服務(wù)器,并進入SYN_SENT狀態(tài),等待服務(wù)器確認;
SYN:同步序列編號(Synchronize Sequence Numbers)。
❤ 第二次握手:服務(wù)器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(seq=k),即SYN+ACK包,此時服務(wù)器進入SYN_RECV狀態(tài);
❤ 第三次握手:客戶端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務(wù)器進入ETABLISHED(TCP連接成功)狀態(tài),完成三次握手。
❤ 完成三次握手,客戶端與服務(wù)器開始傳送數(shù)據(jù)
TCP編程
套接字(Socket)是使用TCP提供了兩臺計算機之間的通信機制。
客戶端程序創(chuàng)建一個套接字,并嘗試連接服務(wù)器的套接字。
當連接建立時,服務(wù)器會創(chuàng)建一個 Socket 對象。客戶端和服務(wù)器現(xiàn)在可以通過對
Socket 對象的寫入和讀取來進行通信。
► 服務(wù)端:
創(chuàng)建服務(wù)端對象,監(jiān)聽一個端口
ServerSocket ss = new ServerSocket(100);
獲取客戶端對象
Socket s = ss.accept(); String ip = s.getInetAddress().getHostAddress();
► 客戶端:
創(chuàng)建客戶端socket服務(wù),把ip和端口作為地址傳進構(gòu)造函數(shù)
Socket s = new Socket("localhost",100);
UDP的概念和實現(xiàn)
UDP(User Datagram Protocol):UDP 是用戶數(shù)據(jù)報協(xié)議的縮寫,一個無連接的協(xié)議。提供了應(yīng)用程序之間要發(fā)送的數(shù)據(jù)的數(shù)據(jù)包。
用戶數(shù)據(jù)包協(xié)議(UDP)是網(wǎng)絡(luò)信息傳輸?shù)牧硪环N形式,基于UDP的通信與基于TCP的通信不同,UDP的信息傳遞更快,但不提供可靠的保證。
UDP編程
發(fā)送端:
建立udp服務(wù),發(fā)送端沒有指定端口,會自動分配一個端口
DatagramSocket ds = new DatagramSocket();
定義數(shù)據(jù)內(nèi)容,并將數(shù)據(jù)封裝成包
byte[] bt = “hello,udp,我來了”.getBytes();
把要發(fā)送的數(shù)據(jù)和ip、port封裝到數(shù)據(jù)包里
DatagramPacket db = new
DatagramPacket(bt,bt.length,InetAddress.getByName(“192.168.1.105”),10000);
通過udp的socket服務(wù)中的功能完成數(shù)據(jù)包的發(fā)送 ds.send(db);
接收端:定義socket服務(wù),監(jiān)聽端口
DatagramSocket ds = new DatagramSocket(10000);
預(yù)先定義好一個數(shù)據(jù)包,用于存儲接收到的數(shù)據(jù)
byte[] bt = new byte[1024];
創(chuàng)建數(shù)據(jù)包對象,用于接收數(shù)據(jù)
DatagramPacket dp = new
DatagramPacket(bt,bt.length);
使用socket服務(wù)的receive方法將接受到的數(shù)據(jù)存儲到數(shù)據(jù)包中
ds.receive(dp);
通過數(shù)據(jù)包對象,獲取數(shù)據(jù)包內(nèi)容
byte[] data = dp.getData();
String ip = dp.getAddress().getHostAddress();
int port = dp.getPort();
TCP和UDP的區(qū)別
TCP:
1,面向連接的協(xié)議,在socket之間進行數(shù)據(jù)傳輸之前必然要建立連接,所以在TCP中需要連接時間。
2,TCP傳輸數(shù)據(jù)無大小限制,一旦連接建立起來,雙方的socket就可以按統(tǒng)一的格式傳輸大的數(shù)據(jù)。
3,TCP是一個可靠的協(xié)議,它確保接收方完全正確地獲取發(fā)送方所發(fā)送的全部數(shù)據(jù)。
UDP:
1,每個數(shù)據(jù)報中都給出了完整的地址信息,因此無需要建立發(fā)送方和接收方的連接。
2,UDP傳輸數(shù)據(jù)時是有大小限制的,每個被傳輸?shù)臄?shù)據(jù)報必須限定在64KB之內(nèi)。
3,UDP是一個不可靠的協(xié)議,發(fā)送方所發(fā)送的數(shù)據(jù)報并不一定以相同的次序到達接收方
TCP和UDP最大的區(qū)別在于是否需要客戶端與服務(wù)端建立連接后才能進行數(shù)據(jù)傳輸。
聊天室
服務(wù)器處理線程
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.Reader; import java.net.Socket; import java.net.SocketException; import java.util.Scanner; public class ServerTask implements Runnable{ private Socket socket; public ServerTask(Socket socket) { // TODO 自動生成的構(gòu)造函數(shù)存根 this.socket = socket; } @Override public void run() { // TODO 自動生成的方法存根 //建立通信后所執(zhí)行的內(nèi)容 System.out.println("歡迎【"+socket.getRemoteSocketAddress().toString()+"】進入聊天室"); //構(gòu)建讀取緩沖 BufferedReader br =null; //http響應(yīng)寫入 PrintWriter pw = null; try { //獲取客戶端輸入的信息 字節(jié)流緩沖成字符流 br = new BufferedReader(new InputStreamReader(socket.getInputStream())); String msg; while((msg=br.readLine()) != null) { msg = "【"+socket.getRemoteSocketAddress().toString()+"】說"+msg; //輸出客戶端信息 System.out.println(msg); //服務(wù)器接收到客戶端的消息發(fā)送消息給客戶端 Scanner scanner = new Scanner(System.in); System.out.println("請輸入要發(fā)送的信息!"); pw = new PrintWriter(socket.getOutputStream(),true); pw.println("服務(wù)器說:"+scanner.nextLine()); pw.flush(); } }catch (SocketException e) { // TODO: handle exception System.out.println(socket.getRemoteSocketAddress().toString()+"退出聊天室!"); } catch (Exception e) { // TODO: handle exception } } }
客戶端處理線程
import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintStream; import java.io.PrintWriter; import java.net.Socket; import java.net.SocketException; import java.util.Scanner; public class ClientTask implements Runnable{ private Socket socket; public ClientTask(Socket socket) { // TODO 自動生成的構(gòu)造函數(shù)存根 this.socket = socket; } @Override public void run() { // TODO 自動生成的方法存根 try { while(true) { Scanner scanner = new Scanner(System.in); System.out.println("請輸入要發(fā)送的信息"); //消息發(fā)送到服務(wù)器 PrintWriter pw = new PrintWriter(socket.getOutputStream(),true); //br.readLine()讀取的消息發(fā)送到服務(wù)器 pw.println(scanner.nextLine()); //讀取服務(wù)器發(fā)送的消息 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); System.out.println(br.readLine()); } } catch (Exception e) { // TODO: handle exception } } }
服務(wù)器
import java.net.ServerSocket; import java.net.Socket; import com.qingsu.chat.Task.ServerTask; public class ChatServer { public static void main(String[] args) { try { //創(chuàng)建服務(wù)端對象 監(jiān)聽一個窗口 ServerSocket serverSocket = new ServerSocket(10622); System.out.println("服務(wù)器創(chuàng)建成功!端口號"+10622); //阻塞 直到有鏈接返回 while(true) { Socket socket = serverSocket.accept();//獲取客戶端對象 //啟動一個線程處理該鏈接 Thread thread = new Thread(new ServerTask(socket)); thread.start(); } } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
客戶端
import java.net.Socket; import com.qingsu.chat.Task.ClientTask; public class ChatClient { public static void main(String[] args) { try { //創(chuàng)建客戶端socket服務(wù),把ip和端口作為地址傳進構(gòu)造函數(shù) Socket socket = new Socket("127.0.0.1",10622); //啟動客戶機線程處理 Thread thread = new Thread(new ClientTask(socket)); thread.start(); }catch (Exception e) { // TODO: handle exception e.printStackTrace(); } } }
效果
到此這篇關(guān)于Java 全面掌握網(wǎng)絡(luò)編程篇的文章就介紹到這了,更多相關(guān)Java 網(wǎng)絡(luò)編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java使用ffmpeg和mencoder實現(xiàn)視頻轉(zhuǎn)碼
這篇文章主要為大家詳細介紹了Java使用ffmpeg和mencoder實現(xiàn)視頻轉(zhuǎn)碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12SpringBoot整合新版SpringSecurity完整過程
Spring Security是保障Spring應(yīng)用程序安全的強大框架,而新版的Spring Security引入了lambda表達式來配置,使得安全配置更加簡潔、優(yōu)雅,本文將介紹如何在Spring Boot項目中整合新版Spring Security,需要的朋友可以參考下2024-02-02Spring Boot中數(shù)據(jù)庫操作Druid和HikariDataSource的詳細過程
這篇文章主要介紹了Spring Boot中數(shù)據(jù)庫操作Druid和HikariDataSource的詳細過程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06Spring?Boot實現(xiàn)JWT?token自動續(xù)期的實現(xiàn)
本文主要介紹了Spring?Boot實現(xiàn)JWT?token自動續(xù)期,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12Mapper層繼承BaseMapper<T>需要引入的pom依賴方式
這篇文章主要介紹了Mapper層繼承BaseMapper<T>需要引入的pom依賴方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01