JAVA深化篇_37—— TCP通信的實現(xiàn)和項目案例
TCP通信的實現(xiàn)和項目案例
TCP通信實現(xiàn)原理
我們提到TCP協(xié)議是面向的連接的,在通信時客戶端與服務(wù)器端必須建立連接。在網(wǎng)絡(luò)通訊中,第一次主動發(fā)起通訊的程序被稱作客戶端(Client)程序,簡稱客戶端,而在第一次通訊中等待連接的程序被稱作服務(wù)器端(Server)程序,簡稱服務(wù)器。一旦通訊建立,則客戶端和服務(wù)器端完全一樣,沒有本質(zhì)的區(qū)別。
“請求-響應(yīng)”模式:
- Socket類:發(fā)送TCP消息。
- ServerSocket類:創(chuàng)建服務(wù)器。
套接字Socket是一種進程間的數(shù)據(jù)交換機制。這些進程既可以在同一機器上,也可以在通過網(wǎng)絡(luò)連接的不同機器上。換句話說,套接字起到通信端點的作用。單個套接字是一個端點,而一對套接字則構(gòu)成一個雙向通信信道,使非關(guān)聯(lián)進程可以在本地或通過網(wǎng)絡(luò)進行數(shù)據(jù)交換。一旦建立套接字連接,數(shù)據(jù)即可在相同或不同的系統(tǒng)中雙向或單向發(fā)送,直到其中一個端點關(guān)閉連接。套接字與主機地址和端口地址相關(guān)聯(lián)。主機地址就是客戶端或服務(wù)器程序所在的主機的IP地址。端口地址是指客戶端或服務(wù)器程序使用的主機的通信端口。
在客戶端和服務(wù)器中,分別創(chuàng)建獨立的Socket,并通過Socket的屬性,將兩個Socket進行連接,這樣,客戶端和服務(wù)器通過套接字所建立的連接使用輸入輸出流進行通信。
TCP/IP套接字是最可靠的雙向流協(xié)議,使用TCP/IP可以發(fā)送任意數(shù)量的數(shù)據(jù)。
實際上,套接字只是計算機上已編號的端口。如果發(fā)送方和接收方計算機確定好端口,他們就可以通信了。
客戶端與服務(wù)器端的通信關(guān)系圖:
TCP/IP通信連接的簡單過程:
位于A計算機上的TCP/IP軟件向B計算機發(fā)送包含端口號的消息,B計算機的TCP/IP軟件接收該消息,并進行檢查,查看是否有它知道的程序正在該端口上接收消息。如果有,他就將該消息交給這個程序。
要使程序有效地運行,就必須有一個客戶端和一個服務(wù)器。
通過Socket的編程順序:
- 創(chuàng)建服務(wù)器ServerSocket,在創(chuàng)建時,定義ServerSocket的監(jiān)聽端口(在這個端口接收客戶端發(fā)來的消息)
- ServerSocket調(diào)用accept()方法,使之處于阻塞狀態(tài)。
- 創(chuàng)建客戶端Socket,并設(shè)置服務(wù)器的IP及端口。
- 客戶端發(fā)出連接請求,建立連接。
- 分別取得服務(wù)器和客戶端Socket的InputStream和OutputStream。
- 利用Socket和ServerSocket進行數(shù)據(jù)傳輸。
- 關(guān)閉流及Socket。
TCP通信入門案例
創(chuàng)建服務(wù)端
1public class BasicSocketServer {
2 public static void main(String[] args) {
3
4 System.out.println("服務(wù)器啟動等待監(jiān)聽。。。。");
5 //創(chuàng)建ServerSocket
6 try(ServerSocket ss =new ServerSocket(8888);
7 //監(jiān)聽8888端口,此時線程會處于阻塞狀態(tài)。
8 Socket socket = ss.accept();
9 //連接成功后會得到與客戶端對應(yīng)的Socket對象,并解除線程阻塞。
10 //通過客戶端對應(yīng)的Socket對象中的輸入流對象,獲取客戶端發(fā)送過來的消息。
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))
12 ){
13
14 System.out.println(br.readLine());
15 }catch(Exception e){
16 e.printStackTrace();
17 System.out.println("服務(wù)器啟動失敗。。。。");
18 }
19 }
20}
創(chuàng)建客戶端
1public class BasicSocketClient {
2 public static void main(String[] args) {
3 //創(chuàng)建Socket對象
4 try(Socket socket =new Socket("127.0.01",8888);
5 //創(chuàng)建向服務(wù)端發(fā)送消息的輸出流對象。
6 PrintWriter pw = new PrintWriter(socket.getOutputStream())){
7 pw.println("服務(wù)端,您好!");
8 pw.flush();
9 }catch(Exception e){
10 e.printStackTrace();
11 }
12 }
13}
14
TCP單向通信
單向通信是指通信雙方中,一方固定為發(fā)送端,一方則固定為接收端。
創(chuàng)建服務(wù)端
1public class OneWaySocketServer {
2 public static void main(String[] args) {
3 System.out.println("服務(wù)端啟動,開始監(jiān)聽。。。。。");
4 try(ServerSocket serverSocket = new ServerSocket(8888);
5 //監(jiān)聽8888端口,獲與取客戶端對應(yīng)的Socket對象
6 Socket socket = serverSocket.accept();
7 //通過與客戶端對應(yīng)的Socket對象獲取輸入流對象
8 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
9 //通過與客戶端對應(yīng)的Socket對象獲取輸出流對象
10 PrintWriter pw = new PrintWriter(socket.getOutputStream())){
11 System.out.println("連接成功!");
12 while(true){
13 //讀取客戶端發(fā)送的消息
14 String str = br.readLine();
15 System.out.println("客戶端說:"+str);
16 if("exit".equals(str)){
17 break;
18 }
19 pw.println(str);
20 pw.flush();
21 }
22 }catch(Exception e){
23 e.printStackTrace();
24 System.out.println("服務(wù)端啟動失敗。。。。。");
25 }
26 }
27}
28
創(chuàng)建客戶端
1public class OneWaySocketClient {
2 public static void main(String[] args) {
3 //獲取與服務(wù)端對應(yīng)的Socket對象
4 try(Socket socket = new Socket("127.0.0.1",8888);
5 //創(chuàng)建鍵盤輸入對象
6 Scanner scanner = new Scanner(System.in);
7 //通過與服務(wù)端對應(yīng)的Socket對象獲取輸出流對象
8 PrintWriter pw = new PrintWriter(socket.getOutputStream());
9 //通過與服務(wù)端對應(yīng)的Socket對象獲取輸入流對象
10 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()))){
11
12 while(true){
13 //通過鍵盤輸入獲取需要向服務(wù)端發(fā)送的消息
14 String str = scanner.nextLine();
15
16 //將消息發(fā)送到服務(wù)端
17 pw.println(str);
18 pw.flush();
19
20 if("exit".equals(str)){
21 break;
22 }
23
24 //讀取服務(wù)端返回的消息
25 String serverInput = br.readLine();
26 System.out.println("服務(wù)端返回的:"+serverInput);
27
28 }
29 }catch(Exception e){
30 e.printStackTrace();
31 }
32 }
33}
TCP雙向通信
雙向通信是指通信雙方中,任何一方都可為發(fā)送端,任何一方都可為接收端。
創(chuàng)建服務(wù)端
1public class TwoWaySocketServer {
2 public static void main(String[] args) {
3 System.out.println("服務(wù)端啟動!監(jiān)聽端口8888。。。。");
4 try(ServerSocket serverSocket = new ServerSocket(8888);
5 Socket socket = serverSocket.accept();
6 //創(chuàng)建鍵盤輸入對象
7 Scanner scanner = new Scanner(System.in);
8 //通過與客戶端對應(yīng)的Socket對象獲取輸入流對象
9 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
10 //通過與客戶端對應(yīng)的Socket對象獲取輸出流對象
11 PrintWriter pw = new PrintWriter(socket.getOutputStream());){
12
13 while(true){
14 //讀取客戶端發(fā)送的消息
15 String str = br.readLine();
16 System.out.println("客戶端說:"+str);
17 String keyInput = scanner.nextLine();
18 //發(fā)送到客戶端
19 pw.println(keyInput);
20 pw.flush();
21 }
22 }catch(Exception e){
23 e.printStackTrace();
24 }
25 }
26}
創(chuàng)建客戶端
public class TwoWaySocketClient {
public static void main(String[] args) {
try(Socket socket = new Socket("127.0.0.1", 8888);
//創(chuàng)建鍵盤輸入對象
Scanner scanner = new Scanner(System.in);
//通過與服務(wù)端對應(yīng)的Socket對象獲取輸入流對象
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//通過與服務(wù)端對應(yīng)的Socket對象獲取輸出流對象
PrintWriter pw = new PrintWriter(socket.getOutputStream());){
while (true) {
String keyInput = scanner.nextLine();
pw.println(keyInput);
pw.flush();
String input = br.readLine();
System.out.println("服務(wù)端說:" + input);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
浙公網(wǎng)安備 33010602011771號