Java 網絡編程】TCP 服務器端 客戶端 簡單示例

      網友投稿 628 2022-05-29

      文章目錄

      I IntelliJ IDEA 創建 Java 項目

      II 客戶端 Socket 創建

      III Socket 客戶端連接服務器端

      IV Socket 兩個端點信息獲取

      V 控制臺人機交互

      VI Socket 客戶端與服務器端交互

      VII ServerSocket 服務器端端口監聽

      VIII ServerSocket 服務器端參數獲取

      IX ServerSocket 服務器端同時與多個客戶端交互方案

      X Socket 客戶端代碼示例

      XI Socket 服務器端代碼示例

      XII 運行客戶端與服務器端代碼

      Java 程序使用 IntelliJ IDEA 進行開發 ;

      創建客戶端項目 :

      菜單欄 File -> New Project , 彈出 New Project 對話框 , 選擇 Gradle 類型下的 java 項目 ;

      輸入 GroupId 和 項目名稱 , 一直點擊下一步到結束 , 最后一個對話框注意選擇項目所在位置 ;

      創建 Socket 需要設置超時時長 ,

      要連接的服務器端的端點信息 ,

      該端點包括 IP 地址和端口號 ;

      //1. 創建 Socket 對象 Socket socket = new Socket(); //2. 設置 Socket 的超時時間 socket.setSoTimeout(5000); //3. 創建連接的端點 , 該端點包括 IP 地址和端口號 InetSocketAddress inetSocketAddress = new InetSocketAddress( Inet4Address.getLocalHost(), //本機IP地址 8000 //端口號 );

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      調用 Socket 對象的 connect 方法 , 即可發起對服務器的連接 ,

      如果連接成功 , 則會繼續執行 , 如果連接失敗或者超時 , 會拋出異常 ;

      //4.. 連接服務器端點 , 并設置超時時間 socket.connect(inetSocketAddress, 5000);

      1

      2

      1. 獲取服務器端點的 IP 地址和端口號 :

      調用 Socket 對象的 getInetAddress 方法獲取服務器端 IP 地址 ,

      調用 getPort 方法獲取服務器端的端口號 ;

      //1. 獲取服務器 IP 地址 InetAddress serverAddress = socket.getInetAddress(); //2. 獲取服務器端口號 int serverPort = socket.getPort();

      1

      2

      3

      4

      2. 獲取客戶端端點的 IP 地址和端口號 :

      調用 Socket 對象的 getLocalAddress 方法 , 可以獲取客戶端的 IP 地址 ,

      調用 getLocalPort 方法可以獲取客戶端的端口號 ;

      //3. 獲取客戶端 IP 地址 InetAddress clientAddress = socket.getLocalAddress(); //4. 獲取客戶端端口號 int clientPort = socket.getLocalPort();

      1

      2

      3

      4

      客戶端信息獲取 ( 人機交互 ) :

      控制臺中等待用戶輸入 , BufferedReader 的 readLine 方法 ,

      可以在控制臺中阻塞等待用戶輸入 ,

      用戶可以在控制臺輸入信息 , 然后客戶端將該信息傳給服務器 ; 下面是鍵盤輸入流的創建和使用過程

      //1. 獲取控制臺輸入流 InputStream is = System.in; //2. 該輸入流會阻塞 , 等待用戶控制臺輸入 BufferedReader br = new BufferedReader(new InputStreamReader(is)); //4. 阻塞命令行 , 等待用戶輸入一行數據, 并存入 string 對象中 String string = br.readLine();

      1

      2

      3

      4

      5

      6

      服務器 -> 客戶端 : 客戶端阻塞等待服務器端發送數據 , 從 Socket 中獲取 BufferedReader 輸入流 , 根據輸入流創建 BufferedReader , 調用 readLine 方法阻塞等待服務器傳回信息 ;

      //1. 獲取服務器端輸入流 cisFromServer = socket.getInputStream(); //2. 將輸入流轉為 BufferedReader BufferedReader brFromServer = new BufferedReader(new InputStreamReader(isFromServer)); //6. 阻塞控制臺 , 從服務器讀取一行數據 String stringFromServer = brFromServer.readLine();

      1

      2

      3

      4

      5

      6

      客戶端 -> 服務器 : 從 Socket 中獲取輸出流 OutputStream , 根據該輸出流創建 PrintStream , 可以將字符串輸出到客戶端 ;

      //4. 獲取客戶端的輸出流 , 用于向服務器端寫出數據 OutputStream os = socket.getOutputStream(); //5. 創建打印流 , 用于向服務器端寫出字符 PrintStream ps = new PrintStream(os); //5. 通過打印流 , 將該字符串傳輸給服務器端 ps.println(string);

      1

      2

      3

      4

      5

      6

      創建 ServerSocket 對象 , 只需要指定端口即可 , 不需要指定 IP 地址 , 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址 , 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號 ;

      //1. 創建服務器套接字 , 只需要指定端口即可 , 不需要指定 IP 地址 // 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址 // 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號 ServerSocket serverSocket = new ServerSocket(8000);

      1

      2

      3

      4

      調用 ServerSocket 對象的 getInetAddress 獲取服務器端的 IP 地址 , 調用該對象的 getLocalPort 可以獲取服務器端監聽的端口號 ;

      //2. 獲取服務器端 IP 地址 InetAddress inetAddress = serverSocket.getInetAddress(); //3. 獲取服務器端口號 int localPort = serverSocket.getLocalPort();

      1

      2

      3

      4

      5

      將與單個客戶端交互的操作封裝到線程中 , 每當與一個新的客戶端建立連接 , 就開啟一個異步線程處理與該客戶端之間的交互 ;

      客戶端處理線程 :

      /** * 異步線程 , 處理單個客戶端連接 * 如果多個客戶端連接 , 就需要創建多個該類, 同時處理多個客戶端連接 */ public static class ClientHandler extends Thread{ //1. 客戶端 Socket 連接 private Socket clientSocket; public ClientHandler(Socket clientSocket) { this.clientSocket = clientSocket; } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      無限循環等待客戶端連接 , 一旦連接成功 , 就開啟一個異步線程 ;

      //II. 等待客戶端連接, 注意此處是無限循環連接 while(true){ //1. 收到一個客戶端連接請求 , 獲取 客戶端 Socket 連接 Socket clientSocket = serverSocket.accept(); //2. 將 Socket 連接傳入 ClientHandler 線程 , 異步處理與客戶端交互操作 ClientHandler clientHandler = new ClientHandler(clientSocket); //3. 啟動 與客戶端 Socket 交互處理 異步線程 clientHandler.start(); }

      1

      【Java 網絡編程】TCP 服務器端 客戶端 簡單示例

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      import java.io.*; import java.net.*; /** * 客戶端 */ public class Client { /** * 客戶端入口函數 * @param args */ public static void main(String[] args){ try { //I. 連接 //1. 創建 Socket 對象 Socket socket = new Socket(); //2. 設置 Socket 的超時時間 socket.setSoTimeout(5000); //3. 創建連接的端點 , 該端點包括 IP 地址和端口號 InetSocketAddress inetSocketAddress = new InetSocketAddress( Inet4Address.getLocalHost(), //本機IP地址 8000 //端口號 ); //4.. 連接服務器端點 , 并設置超時時間 socket.connect(inetSocketAddress, 5000); //5. 如果連接成功會繼續執行下面的操作, 如果失敗會根據失敗情況拋出異常 //II. 獲取 Socket 連接兩個端點的屬性, IP 地址和端口號 //1. 獲取服務器 IP 地址 InetAddress serverAddress = socket.getInetAddress(); //2. 獲取服務器端口號 int serverPort = socket.getPort(); //3. 獲取客戶端 IP 地址 InetAddress clientAddress = socket.getLocalAddress(); //4. 獲取客戶端端口號 int clientPort = socket.getLocalPort(); System.out.println("服務器連接成功\n服務器地址 : " + serverAddress + " , 服務器端口號 : " + serverAddress + "\n客戶端地址 : " + clientAddress + " , 客戶端端口號 : " + clientPort); //向服務器端發送數據 sendToServer(socket); //III. 關閉 Socket 連接 socket.close(); System.out.println("客戶端 Socket 連接關閉"); } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { //客戶端可能掛了 , 需要重啟 } } public static void sendToServer(Socket socket){ try { //I. 獲取用戶控制臺輸入信息 //1. 獲取控制臺輸入流 InputStream is = System.in; //2. 該輸入流會阻塞 , 等待用戶控制臺輸入 BufferedReader br = new BufferedReader(new InputStreamReader(is)); //II. 將用戶輸入信息上傳到服務器 //4. 獲取客戶端的輸出流 , 用于向服務器端寫出數據 OutputStream os = socket.getOutputStream(); //5. 創建打印流 , 用于向服務器端寫出字符 PrintStream ps = new PrintStream(os); //III. 從服務器獲取信息 , 這里循環讀取數據, 接收到 服務器端的 quit 字符串才退出 //1. 獲取服務器端輸入流 InputStream isFromServer = socket.getInputStream(); //2. 將輸入流轉為 BufferedReader BufferedReader brFromServer = new BufferedReader(new InputStreamReader(isFromServer)); //3. 循環控制變量 , 退出時設置為 false boolean isReadFromServer = true; while (isReadFromServer){ //4. 阻塞命令行 , 等待用戶輸入一行數據, 并存入 string 對象中 String string = br.readLine(); //5. 通過打印流 , 將該字符串傳輸給服務器端 ps.println(string); //6. 阻塞控制臺 , 從服務器讀取一行數據 String stringFromServer = brFromServer.readLine(); //7. 根據服務器返回的數據進行不同操作 if("quit".equals(stringFromServer)){ //停止循環 isReadFromServer = false; }else{ System.out.println(stringFromServer); } } //IV. 釋放資源 br.close(); ps.close(); brFromServer.close(); } catch (IOException e) { e.printStackTrace(); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      112

      113

      114

      115

      116

      117

      118

      119

      120

      121

      122

      123

      124

      125

      126

      127

      128

      129

      130

      131

      import java.io.*; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; /** * 服務器端 */ public class Server { /** * 服務器端入口函數 * @param args */ public static void main(String[] args){ try { //I. 創建服務器套接字, 并監聽端口 //1. 創建服務器套接字 , 只需要指定端口即可 , 不需要指定 IP 地址 // 其 IP 地址就是本機的 IP 地址 , 如果機器有多個 IP 地址 // 如果沒有指定 IP 地址 , 那么會監聽所有的 IP 地址的指定端口號 ServerSocket serverSocket = new ServerSocket(8000); //2. 獲取服務器端 IP 地址 InetAddress inetAddress = serverSocket.getInetAddress(); //3. 獲取服務器端口號 int localPort = serverSocket.getLocalPort(); System.out.println("服務器開啟\nIP 地址 : " + inetAddress + " , 端口號 : " + localPort); //II. 等待客戶端連接, 注意此處是無限循環連接 while(true){ //1. 收到一個客戶端連接請求 , 獲取 客戶端 Socket 連接 Socket clientSocket = serverSocket.accept(); //2. 將 Socket 連接傳入 ClientHandler 線程 , 異步處理與客戶端交互操作 ClientHandler clientHandler = new ClientHandler(clientSocket); //3. 啟動 與客戶端 Socket 交互處理 異步線程 clientHandler.start(); } } catch (IOException e) { e.printStackTrace(); } } /** * 異步線程 , 處理單個客戶端連接 * 如果多個客戶端連接 , 就需要創建多個該類, 同時處理多個客戶端連接 */ public static class ClientHandler extends Thread{ //1. 客戶端 Socket 連接 private Socket clientSocket; //2. 循環控制變量 private boolean loopFlag = true; public ClientHandler(Socket clientSocket) { this.clientSocket = clientSocket; } @Override public void run() { super.run(); //I. 獲取客戶端相關信息 //1. 獲取客戶端的 IP 地址 InetAddress inetAddress = clientSocket.getInetAddress(); //2. 獲取客戶端的端口號 int port = clientSocket.getPort(); //3. 打印客戶端的信息 System.out.println("客戶端信息 : \nIP 地址 : " + inetAddress + " , 端口號 : " + port); try { //II. 創建與客戶端交互的輸入輸出流 //1. 獲取客戶端 Socket 輸出流 , 用于向客戶端發送數據 OutputStream os = clientSocket.getOutputStream(); //2. 創建打印流 , 用于向客戶端輸出數據 PrintStream ps = new PrintStream(os); //3. 獲取客戶端 Socket 輸入流 , 用于接收客戶端數據 InputStream is = clientSocket.getInputStream(); //4. 獲取客戶端的字符輸入流 , 該輸入流可以阻塞等待客戶端輸入 BufferedReader br = new BufferedReader(new InputStreamReader(is)); //III. 循環處理與客戶端交互的信息 while (loopFlag){ //1. 等待客戶端輸入 String string = br.readLine(); //2. 處理客戶端輸入 if("quit".equals(string)){ //如果客戶端發送退出, 那么停止循環, 將該信息在送回客戶端 loopFlag = false; //將信息發送到客戶端 ps.println("quit"); }else{ //將信息打印到控制臺 System.out.println(string); //將發送成功信息返回給客戶端 ps.println("發送成功 , 大小 " + string.length() + " 字節"); } } //IV. 關閉相關資源 ps.close(); br.close(); } catch (IOException e) { e.printStackTrace(); }finally { try { //如果出現異常 , 將該 Socket 關閉 clientSocket.close(); } catch (IOException e) { e.printStackTrace(); } } System.out.println("客戶端退出 : \nIP 地址 : " + inetAddress + " , 端口號 : " + port); } } }

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      14

      15

      16

      17

      18

      19

      20

      21

      22

      23

      24

      25

      26

      27

      28

      29

      30

      31

      32

      33

      34

      35

      36

      37

      38

      39

      40

      41

      42

      43

      44

      45

      46

      47

      48

      49

      50

      51

      52

      53

      54

      55

      56

      57

      58

      59

      60

      61

      62

      63

      64

      65

      66

      67

      68

      69

      70

      71

      72

      73

      74

      75

      76

      77

      78

      79

      80

      81

      82

      83

      84

      85

      86

      87

      88

      89

      90

      91

      92

      93

      94

      95

      96

      97

      98

      99

      100

      101

      102

      103

      104

      105

      106

      107

      108

      109

      110

      111

      112

      113

      114

      115

      116

      117

      118

      119

      120

      121

      122

      123

      124

      125

      126

      127

      128

      129

      130

      131

      132

      133

      134

      135

      136

      137

      138

      139

      140

      141

      142

      143

      144

      145

      1. 編譯兩個 Java 代碼 : 選擇菜單欄 -> Build -> Rebuild Project 選項 , 獲取到 Client.class 和 Server.class 文件 ;

      2. 字節碼文件地址 : 編譯后的 class 字節碼文件在工程目錄的 out\production\classes 目錄下 ;

      打開兩個命令行界面 , 首先進入該目錄 , 先運行服務器端 , 在命令行中輸入 java Server , 即開啟了服務器端 ; 再打開客戶端 , 在另一個命令行中運行 java Client , 即開啟了客戶端 ;

      客戶端輸入文字 , 與服務器端交互 :

      Java Socket編程 TCP/IP 網絡

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:汽車傳感器超強科普:一次性看懂各類傳感器的優劣勢及應用
      下一篇:JAVA編程講義之數組
      相關文章
      亚洲Av无码乱码在线观看性色| 亚洲国产成人片在线观看| 亚洲国产成人一区二区三区| 久久影视国产亚洲| 久久久久国产成人精品亚洲午夜| 亚洲精品专区在线观看| www.91亚洲| 亚洲综合精品网站| 亚洲精品在线视频| 亚洲人成影院在线无码按摩店| 国产美女亚洲精品久久久综合| 伊人久久亚洲综合| 亚洲欧洲美洲无码精品VA| 亚洲色无码一区二区三区| 亚洲国产日韩在线视频| 亚洲av无码一区二区三区网站| 国产亚洲精品自在久久| 亚洲va无码手机在线电影| 亚洲av无码国产精品夜色午夜 | 久久亚洲精品成人av无码网站| 婷婷久久久亚洲欧洲日产国码AV | 亚洲国产成人无码AV在线| 亚洲AV无码一区二区三区网址| 自拍偷自拍亚洲精品播放| 亚洲国产成人精品久久久国产成人一区二区三区综 | 亚洲在成人网在线看| 亚洲国产av高清无码| 一区二区亚洲精品精华液| 亚洲av永久中文无码精品综合| 色偷偷噜噜噜亚洲男人| 亚洲精品成人在线| 亚洲精品无码高潮喷水在线| 亚洲国产天堂久久综合网站| 亚洲成综合人影院在院播放| 国产成人亚洲合集青青草原精品| 亚洲中文无码亚洲人成影院| 无码不卡亚洲成?人片| 国内精品久久久久久久亚洲| 无码乱人伦一区二区亚洲| 亚洲国产夜色在线观看| 亚洲人成色77777在线观看|