Java后端學習精華之TCP通信傳輸協(xié)議詳解
上篇教程回顧
ServerSocket --監(jiān)聽客戶端的連接,他的作用主要是建立一個連接
-ServerSocket -建立連接,拿到一個Socket
-Telnet 127.0.0.1 8888- 客戶端使用Telnet訪問服務端 建立連接
-服務端可以拿到一個Socket的對象
-獲取這個對象的輸入輸出流
-寫入和讀取數(shù)據(jù)
Socket連接模型

服務端和客戶端通過Socket進行連接,雖然是一個Socket,但是相當于把這一個Socket分成了兩個管道,服務端拿著這兩根管道的一段,客戶端拿著這兩根管道的另一端。
- Server的input與Client的output相連
- 客戶端發(fā)送數(shù)據(jù),從Client的output發(fā)送,傳輸?shù)絊erver的input接收
- 服務端發(fā)送數(shù)據(jù),從Server的output發(fā)送,傳輸?shù)紺lient的input接收
- 如果實現(xiàn)雙端收發(fā)通信,每個程序至少需要兩個線程
消息協(xié)議
TCP:面向連接
UDP:不需要建立連接 類似數(shù)據(jù)報
TCP:穩(wěn)定,要求發(fā)送數(shù)據(jù)前必須確認雙方都可以收發(fā)消息
連接過程 : 三次握手
Server--------------------- Client
1: 監(jiān)聽-----------------------發(fā)送請求
這步之后,服務端知道客戶端可以發(fā)數(shù)據(jù)
2:收到請求,應答------------收到應答消息,發(fā)送應答包給s
這步之后,客戶端知道服務端可收發(fā)數(shù)據(jù)
3:收到應答
這步之后,服務端知道客戶端可以收數(shù)據(jù)
傳輸過程中數(shù)據(jù)類型需要了解的細節(jié)
char:16bit 兩個字節(jié)Byte
數(shù)據(jù)發(fā)送的單位:數(shù)據(jù)每次發(fā)送一個byte,一個char需要發(fā)送兩次單字節(jié)
發(fā)送文字消息
- 第一部分應發(fā)送字符串的長度,以便確定字節(jié)數(shù)組的長度
- 對方,讀取的第一個字節(jié)是消息長度,定義一個固定容量大小的容器
- 第二部分為消息內容
- 對方,讀取對應長度的字節(jié)后,將其轉成對應的數(shù)據(jù)(String對象)
數(shù)據(jù)類型:
- 整數(shù)型:byte short int long
- 浮點型:float double
- 字符型:char
- 布爾型:boolean
- char=16bit=2 byte unicode編碼
- utf-8:1-6個字節(jié)組成一個漢字
1100 1101 1010
如這個數(shù)據(jù)第一個字節(jié)有兩個1,則代表它是一個漢子,并且后面兩個字節(jié)都表示這個漢字,如果有111就讀取后面三個字節(jié)
因為英文用ASCII碼存儲0-127,第一位不可能是1,通過第一個字節(jié)可以判斷是中文還是英文
- 英文字母全部兼容:ASCII 0-127 二進制碼:0-255,所以0-127一定以0開頭,漢字是16bit 0-65536
TCP通信代碼
通過自己編寫一個客戶端和服務端,實現(xiàn)消息的首發(fā),這里的核心主要是自己編寫通信協(xié)議,我在這里第一次發(fā)送到是數(shù)據(jù)的長度,并且做了數(shù)據(jù)加密,客戶端需要解析這個數(shù)據(jù)長度,并創(chuàng)建對應長度的數(shù)組,才能正確讀取消息內容
MsgClient
package com.lding.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @program: Net
* @description: Tcp客戶端測試
* @author: 王丁
* @date: 2021-09-20 10:04
**/
public class TcpClient {
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",8888);
OutputStream output=socket.getOutputStream();
InputStream input=socket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(input);
// byte[] msgbyte=new byte[30];
// input.read(msgbyte);
// System.out.println("服務器說:"+new String(msgbyte));
int length1=input.read();
int length2=input.read();
int msglength=length2*3+length1;
System.out.println("消息長度為:"+msglength);
byte[] msgbytes=new byte[msglength];
input.read(msgbytes);
String getmsg=new String(msgbytes);
System.out.println("服務器說:"+getmsg);
}
}
MsgServer
package com.lding.net;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* @program: Net
* @description: Tcp服務端測試
* @author: 王丁
* @date: 2021-09-20 10:03
**/
public class TcpServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8888);
//監(jiān)聽客戶端的Socket連接
System.out.println("服務端開啟:ip:"+serverSocket.getInetAddress().getHostAddress()+"端口號:"+serverSocket.getLocalSocketAddress());
System.out.println("正在等待有緣人......");
Socket socketClient = serverSocket.accept();
System.out.println("客戶端已連接:"+socketClient.getInetAddress());
System.out.println("客戶端端口"+socketClient.getPort());
OutputStream output=socketClient.getOutputStream();
InputStream input=socketClient.getInputStream();
// output.write("服務器連接成功!?。?.getBytes());
// output.flush();//刷新緩沖,管道強制刷出
String msg="服務器連接成功?。?!中秋快樂!<include/bits/stdc++.h> using namespace std";
byte[] msgBytes=msg.getBytes();
int length1=msgBytes.length%3;
int length2=msgBytes.length/3;
output.write(length1);
output.write(length2);
output.write(msgBytes);
output.flush();
// while(input.read()!=-1){
// System.out.println((char) input.read());
// }
}
}
運行結果


還可以完善的地方
1、之后通信協(xié)議可以加入,通過客戶端列表,轉發(fā)消息內容到多個客戶端
2、攜帶用戶名、目標用戶名等等
到此這篇關于Java后端學習精華之TCP通信傳輸協(xié)議詳解的文章就介紹到這了,更多相關Java TCP通信內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IDEA如何使用spring-Initializr快速搭建SpringBoot
這篇文章主要介紹了IDEA如何使用spring-Initializr快速搭建SpringBoot問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05
Java的Spring框架中bean的繼承與內部bean的注入
這篇文章主要介紹了Java的Spring框架中bean的繼承與內部bean的注入,Spring框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2015-12-12
java使用JDBC動態(tài)創(chuàng)建數(shù)據(jù)表及SQL預處理的方法
這篇文章主要介紹了java使用JDBC動態(tài)創(chuàng)建數(shù)據(jù)表及SQL預處理的方法,涉及JDBC操作數(shù)據(jù)庫的連接、創(chuàng)建表、添加數(shù)據(jù)、查詢等相關實現(xiàn)技巧,需要的朋友可以參考下2017-08-08
Sentinel Dashboard限流規(guī)則保存方式
這篇文章主要介紹了Sentinel Dashboard限流規(guī)則保存方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06
SpringMVC @RequestBody Date類型的Json轉換方式
這篇文章主要介紹了SpringMVC @RequestBody Date類型的Json轉換方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10
java使用CountDownLatch等待多線程全部執(zhí)行完成
這篇文章主要為大家詳細介紹了使用CountDownLatch等待多線程全部執(zhí)行完成,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-10-10

