闭关修炼(十一)网络通信
你問我互聯網工程設計學了啥?emm。。。感覺上課都在照著抄代碼,要說什么印象特別深,腦海里還真沒剩啥了。
文章目錄
- 網絡通訊
- IP
- 端口號
- 客戶端和服務端
- TCP與UDP
- 什么是網絡模型
- TCP和UDP的區別
- 什么是三次握手
- 什么是四次揮手
- 為什么建立連接協議是三次握手,而關閉連接卻是四次握手呢?
- UDP的客戶端與服務端通訊例子
- TCP的客戶端和服務端
網絡通訊
IP
定位某臺計算機
端口號
定位某個應用程序
客戶端和服務端
發起請求端為客戶端,發送響應端為服務端
TCP與UDP
什么是網絡模型
4層,應用層(HTTP協議),傳輸層(TCP,UDP協議),網絡層(IP協議),鏈路層(以太網協議)
任何計算機語言通訊,底層都使用socket技術
為什么socket支持這么多語言?
socket遵循一個二進制的端口號+IP的規范進行傳輸,所以可以跨語言使用。
socket核心協議:TCP和UDP
TCP和UDP的區別
UDP面向無連接 — 即不建立連接、限制傳輸64k的不可靠協議
TCP面向連接協議,三次握手后進行通訊,通過字節流進行傳輸,效率比UDP低,但比UDP靠譜。
什么是三次握手
當三次握手成功之后,才開始進行數據傳輸。
第一次握手:客戶端:發送報文給服務端,SYN=J
第二次握手:服務端:發送報文給客戶端,ACK=J+1,SYN=K
第三次握手:客戶端:發送報文給服務端,ACK=K+1
什么是四次揮手
結束通信會進行四次揮手。
第一次揮手:客戶端:發送FIN=M
第二次揮手:服務端:發送SYN=M+1
第三次揮手:服務端:發送FIN=N
第四次揮手:客戶端:發送ACK=N+1
為什么建立連接協議是三次握手,而關閉連接卻是四次握手呢?
這是因為服務端的 LISTEN 狀態下的 SOCKET 當收到 SYN 報文的建連請求后,它可以把 ACK 和 SYN(ACK 起應答作用,而 SYN 起同步作用)放在一個報文里來發送。但關閉連接時,當收到對方的 FIN 報文通知時,它僅僅表示對方沒有數據發送給你了,但是你還可以給對方發送數據,也有這么種可能,你還有一些數據在傳給對方的途中,所以你不能立馬關閉連接,也即你可能還需要把在傳輸途中的數據給對方之后,又或者,你還有一些數據需要傳輸給對方后,(再關閉連接)再發送FIN 報文給對方來表示你同意現在可以關閉連接了,所以它這里的 ACK 報文和 FIN 報文多數情況下都是分開發送的。
UDP的客戶端與服務端通訊例子
UDP核心是DatagramSocket和DatagramPacket。
服務端,用DatagramSocket+傳入端口創建服務器,并且建立DatagramPacket來接收客戶端的數據包
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket;/*** udp服務器** @author uuz* @date 2021/01/11*/ public class UdpServer {/*** 端口號*/static int PORT = 9009;/*** 緩沖區大小*/static int BUFFER_SIZE = 1024;/*** 正在運行*/static boolean IS_RUNNING = true;public static void main(String[] args) throws IOException {System.out.println("UDP SERVER IS RUNNING...");// 創建服務器端口號,默認使用本機ipDatagramSocket datagramSocket = new DatagramSocket(PORT);while (IS_RUNNING) {// 定義數據包byte[] buf = new byte[BUFFER_SIZE];DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);// 接收客戶端發來的數據,將數據封裝給數據包,此方法阻塞接收datagramSocket.receive(datagramPacket);// 打印來源地址System.out.printf("來源IP地址: %s:%s\n內容: %s\n",datagramPacket.getAddress(),datagramPacket.getPort(),new String(datagramPacket.getData(), 0, datagramPacket.getLength()));}}}客戶端,構造DatagramPacket,傳入服務器IP和端口,使用datagramSocket發送
import java.io.IOException; import java.net.*;public class UdpClient {static String REMOTE_ADDRESS = "127.0.0.1";public static void main(String[] args) throws IOException {System.out.println("新建Socket客戶端");// 創建一個socket客戶端DatagramSocket datagramSocket = new DatagramSocket();// 要發送的內容String content = "這是一條測試信息";// 轉換成byte[]byte[] bytes = content.getBytes();// 創建數據包,帶上要的發送IP和端口DatagramPacket dp = new DatagramPacket(bytes,bytes.length,InetAddress.getByName(REMOTE_ADDRESS),UdpServer.PORT);datagramSocket.send(dp);datagramSocket.close();System.out.println("發送UDP結束");} }TCP的客戶端和服務端
服務器端
import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket;/*** tcp服務器** @author uuz* @date 2021/01/11*/ public class TCPServer {static int PORT = 8889;static int BUFFER_SIZE = 1024;static boolean isRunning = true;public static void main(String[] args) throws IOException {System.out.println("TCP SERVER START");// 創建服務器端口號ServerSocket serverSocket = new ServerSocket(PORT);while (isRunning) {// 阻塞接收信息Socket socket = serverSocket.accept();// 獲取socket傳輸的字節流InputStream inputStream = socket.getInputStream();// 將字節流轉為Stringbyte[] bytes = new byte[BUFFER_SIZE];int length = inputStream.read(bytes);// 轉換成StringString data = new String(bytes, 0, length);// 打印輸出System.out.println(data);}serverSocket.close();} }客戶端
import java.io.IOException; import java.io.OutputStream; import java.net.Socket;public class TCPClient {static String REMOTE_ADDRESS = "127.0.0.1";public static void main(String[] args) throws IOException {System.out.println("tcp 客戶端");// 連接服務器Socket socket = new Socket(REMOTE_ADDRESS, TCPServer.PORT);// 獲取字節流OutputStream outputStream = socket.getOutputStream();// 發送outputStream.write("這是一條測試".getBytes());// 關閉連接socket.close();} }服務端多線程版
import lombok.AllArgsConstructor; import lombok.Data; import lombok.SneakyThrows;import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;/*** tcp服務器** @author uuz* @date 2021/01/11*/ public class TCPServer {static int PORT = 8889;static int BUFFER_SIZE = 1024;static int THREAD_POOL_SIZE = 10;static boolean isRunning = true;public static void main(String[] args) throws IOException {System.out.println("TCP SERVER START");// 創建服務器端口號ServerSocket serverSocket = new ServerSocket(PORT);// 創建線程池ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);while (isRunning) {// 阻塞接收信息Socket socket = serverSocket.accept();executorService.execute(new Runnable() {@SneakyThrows@Overridepublic void run() {// 獲取socket傳輸的字節流InputStream inputStream = socket.getInputStream();// 將字節流轉為Stringbyte[] bytes = new byte[BUFFER_SIZE];int length = inputStream.read(bytes);// 轉換成StringString data = new String(bytes, 0, length);// 打印輸出System.out.println(data);}});}serverSocket.close();}}總結
以上是生活随笔為你收集整理的闭关修炼(十一)网络通信的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Riak - 安装运维篇(1)
- 下一篇: 东风岚图配谈“梦想”吗?