一、多執行緒的TCP網路編程
- 如果需要進行多次資料互動,就可以在程式中設定一個回圈,不斷向對方發送請求,即可完成多次資料互動,同樣,如果需要讓服務器同時回應多個客戶端的請求,可以使用多執行緒的方法,也就是服務器端沒接收到一個新的連接請求,就啟動一個專門的執行緒與客戶端進行互動,
- 本測驗程式可以分為三類:客戶端類、服務器類和邏輯執行緒類
- 首先是客戶端類
package com.bjpowernode.java_learning; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; import java.util.Scanner; public class D127_1_ClientTest { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); String input = null; Socket socket = null; DataInputStream in = null; DataOutputStream out = null; String serverIP = "127.0.0.1"; //服務器端IP int port = 5050; try { socket = new Socket(serverIP,port); //連接服務器 in = new DataInputStream(socket.getInputStream()); //創建輸入流 out = new DataOutputStream(socket.getOutputStream());//創建輸出流 System.out.println("請輸入一個待計算的四則運算運算式"); while(scanner.hasNext()) { input = scanner.nextLine(); //從鍵盤輸入一個待計算的四則運算運算式 if(!input.contentEquals("0")) { out.writeUTF(input); //向服務器發送運算請求 String result = in.readUTF(); //等待讀取運算結果 System.out.println("服務器回傳的計算結果:"+result); System.out.println("請輸入一個正整數的四則運算運算式(輸入0退出):"); }else { break; //請求結果 } } }catch(Exception e) { System.out.println("與服務器連接中斷"); }finally { try { in.close(); //關閉網路連接 out.close(); socket.close(); System.out.println("連接結束"); }catch(Exception e) { } } } }
- 接下來是服務器端類
package com.bjpowernode.java_learning; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import com.bjpowernode.java_learning.D127_3_ThreadTest; public class D127_2_ServerTest { public static void main(String[] args) { ServerSocket server_socket = null; Socket socket = null; int port = 5050; while(true) { try { server_socket = new ServerSocket(port); System.out.println("服務器啟動!"); }catch(IOException e1) { System.out.println("正在監聽"); //ServerSocket物件不能重復創建 } try { System.out.println("等待客戶請求!"); socket = server_socket.accept(); System.out.println("客戶的地址:"+socket.getInetAddress() + ":" + socket.getPort()); }catch(IOException e) { System.out.println("正在等待客戶"); } if(socket!=null) { new D127_3_ThreadTest(socket); //為每個客戶啟動一個專門的執行緒 } } } }
- 最后是邏輯執行緒類
package com.bjpowernode.java_learning; import java.io.DataInputStream; import java.io.DataOutputStream; import java.net.Socket; public class D127_3_ThreadTest extends Thread { Socket socket = null; DataInputStream in = null; DataOutputStream out = null; String str; String response; String ip; int port; public D127_3_ThreadTest(Socket socket) { this.socket = socket; start(); } public void run() { try { in = new DataInputStream(socket.getInputStream()); //創建輸入流 out = new DataOutputStream(socket.getOutputStream()); //創建輸出流 ip = socket.getInetAddress().getHostAddress(); //客戶端IP地址 port = socket.getPort(); //客戶端的埠號 while(true) { str = in.readUTF(); //獲取客戶端的運算式 System.out.println("客戶端" + ip + ":" + port + "發送的請求內容:"); System.out.println(str+"=?"); if(str.contentEquals("0")) { System.out.println("連接結束"); break; }else { response = doComputer(str); //對運算式進行計算 out.writeUTF(response); //回應計算結果 } } }catch(Exception e) { System.out.println("連接結束"); }finally { try { in.close(); out.close(); socket.close(); }catch(Exception e) { } } } public String doComputer(String str) { String input; String[] sym; String[] data; int a=0,b=0,result=0; input = str; data = input.split("\\D+"); sym = input.split("\\d+"); a = Integer.parseInt(data[0]); b = Integer.parseInt(data[1]); try { switch(sym[1]) { case "+": result = a + b; break; case "-": result = a - b; break; case "*": result = a * b; break; case "/": result = a / b; } System.out.println("計算結果:"+input+"="+result); return String.valueOf(result); }catch(java.lang.ArithmeticException e) { System.out.println("資料錯誤!"); return "資料錯誤"; } } }
- 這樣我們就做完了所有的作業,那么接下來進行啟動該專案
- 首先啟動服務器的類,運行結果如下:

- 然后啟動客戶端類

- 我們在客戶端類中cosole界面輸入
3*5然后回車

- 從上面的運行結果來看,得到了我們想要的結果,那么接下來輸入
0來結束這個專案的運行

總結:在撰寫代碼程序中我們遇到的問題,或者以前忘記的知識點:
1.服務器端類中:
(1)server_socket.accept() 一直處于阻塞直到接收了socket發來的請求,并回傳一個socket物件;
(2)寫一了一個多執行緒類,來給每個客戶一個執行緒;
2.客戶端類 \ (1)DataInputStream(socket.getInputStream()) \ socket的成員方法來獲取輸入流,并回傳一個InputStream物件,然后經過java.io.DataInputStream方法轉換為專有的流,
(2)DataOutputStream物件.writeUTF(String result) 用于傳入字串
(3)DataInputStream物件.readUTF() 用于讀取字串
3.多執行緒類
(1) 多執行緒重寫了run方法
(2) 客戶端和服務器端的讀和寫是正相反的,
二、原始碼:
- D127_1_ClientTest.java
- D127_2_ServerTest.java
- D127_3_ThreadTest.java
- https://github.com/ruigege66/Java/blob/master/D127_1_ClientTest.java
- https://github.com/ruigege66/Java/blob/master/D127_2_ServerTest.java
- https://github.com/ruigege66/Java/blob/master/D127_3_ThreadTest.java
- CSDN:https://blog.csdn.net/weixin_44630050
- 博客園:https://www.cnblogs.com/ruigege0000/
- 歡迎關注微信公眾號:傅里葉變換,個人賬號,僅用于技術交流,后臺回復“禮包”獲取Java大資料學習視頻禮包

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/151073.html
標籤:Java
下一篇:mybatis入門學習
