Java中TCP通信的實現方法詳解
0、TCP通信
傳輸控制協議(TCP,Transmission Control Protocol)是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協議,

如果使用了 WireShark 工具,可以看到一次TCP連接建立時的整個過程。

1、單向通信
單向通信中,一方固定為信息發(fā)送方,另外一方則固定為信息的接收方。
1.1 單向通信中的服務端
服務端即為信息的接收方。
使用 ServerSocket 類創(chuàng)建服務端,并將服務的端口設置為 9527;
serverSocket.accept() 方法用于監(jiān)聽對 9527 端口的連接,該方法為阻塞式方法,當接收到數據后,程序才會繼續(xù)向下執(zhí)行,否則一直處于等待狀態(tài);
當接收到數據后,因是使用字節(jié)流傳輸,這里使用 使用 InputStreamReader 的轉換流將字節(jié)數據轉換為字符串,并使用 BufferedReader 進行讀取和輸出;
當服務端接收到客戶端的請求后,需要向客戶端發(fā)出響應數據,使用 PrintWriter 發(fā)送響應報文,需要使用 flush() 方法,將消息發(fā)出;
當客戶端發(fā)出的消息為“再見”時,服務端即退出通信,關閉服務。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
System.out.println("服務器啟動!");
try {
ServerSocket serverSocket = new ServerSocket(9527);
Socket socket = serverSocket.accept();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
PrintWriter pw = new PrintWriter(socket.getOutputStream());
System.out.println("接收客戶端消息");
while (true){
String in = br.readLine();
System.out.println("接收到客戶端發(fā)來的請求:" + in);
if("再見".equals(in)){
break;
}
pw.print(in + "回報");
pw.flush();
}
} catch (IOException e) {
System.out.println("服務啟動失敗!");
e.printStackTrace();
}
}
}啟動后,服務端輸出為:
服務器啟動!
1.2 單向通信中的客戶端
客戶端即為信息的發(fā)送方。
- 創(chuàng)建 Socket 對象,?
?Socket("localhost", 9527)?? 和端口為 9527 的服務建立通信; - 接收和發(fā)送消息的方法,和服務端相同;
- 為了能夠向服務端循環(huán)發(fā)送消息,使用了死循環(huán),當用戶輸入“再見”時,終止循環(huán);
- 使用 Scanner 對象接收鍵盤輸入。
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try {
Socket socket = new Socket("localhost", 9527);
//讀取輸入流
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//獲取輸出流
PrintWriter pw = new PrintWriter(socket.getOutputStream());
//從鍵盤獲取輸入
Scanner scanner = new Scanner(System.in);
while (true){
//從控制臺獲取向服務端發(fā)送的消息
String next = scanner.next();
pw.println(next);
pw.flush();
String s = br.readLine();
System.out.println("收到服務器響應:" + s);
if("再見".equals(next)){
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}1.3 建立通信
啟動客戶端后,并在客戶端的控制臺輸入“你好”,觀察服務端和客戶端的控制臺

在客戶端的控制臺輸入“再見”,觀察服務端和客戶端的控制臺

2、雙向通信
雙向通信中,雙方都可以既是信息的發(fā)送方,也可以是信息的接收方。
2.1 雙向通信中的服務端
在服務端設置發(fā)消息和收消息。
在服務端也使用了 Scanner ,用來接收控制臺輸入,并將其發(fā)送給客戶端。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
public class Server {
public static void main(String[] args) {
try{
ServerSocket serverSocket = new ServerSocket(9528);
Socket socket = serverSocket.accept();
//獲取客戶端請求
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//獲取鍵盤輸入
Scanner scanner = new Scanner(System.in);
//發(fā)送消息到客戶端
PrintWriter pw = new PrintWriter(socket.getOutputStream());
while (true){
String input = br.readLine();
System.out.println("收到客戶端請求: " + input);
String output = scanner.nextLine();
pw.println(output);
pw.flush();
if("再見".equals(input)){
break;
}
}
}catch (Exception e){
e.printStackTrace();
System.out.println("服務啟動失?。?);
}
}
}2.2 雙向通信中的客戶端
在客戶端設置發(fā)消息和收消息
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) {
try{
Socket socket = new Socket("127.0.0.1", 9528);
//獲取服務端響應
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//獲取客戶端用戶輸入
Scanner scanner = new Scanner(System.in);
//向服務端發(fā)送請求
PrintWriter pw = new PrintWriter(socket.getOutputStream());
System.out.println("準備接收請求……");
while (true){
String output = scanner.next();
pw.println(output);
pw.flush();
String input = br.readLine();
System.out.println("來自服務端的響應: " + input);
if("再見".equals(output)){
break;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
}2.3 建議通信
啟動服務端及客戶端,并在控制臺輸入內容:

存在的問題:
這樣的通信,需要客戶端發(fā)一次消息 -》 服務端回一次消息,如果客戶端同時發(fā)送兩條消息,就會導致消息不同步。
比如下邊的情況:

這個問題可以先思考下,應該如何解決,后邊將會給出解決方案。
總結
到此這篇關于Java中TCP通信的實現方法的文章就介紹到這了,更多相關Java TCP通信實現內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Spring的@Validation和javax包下的@Valid區(qū)別以及自定義校驗注解
這篇文章主要介紹了Spring的@Validation和javax包下的@Valid區(qū)別以及自定義校驗注解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-01-01

