首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 編程那些事兒 104:TCP 網絡編程進階——連接復用與多線程並發服務端

     編輯:Java 相關知識

一、如何復用 Socket 連接?

前示例中客戶端建立連接僅發送一次數據即關閉,實際應建立一次連接進行多次交換。做法:將數據交換邏輯置入循環。

客戶端復用示例

package tcp;
import java.io.*;
import java.net.*;

public class MulSocketClient {
public static void main(String[] args) {
Socket socket = null;
InputStream is = null;
OutputStream os = null;
String serverIP = "127.0.0.1";
int port = 10000;
String data[] = {"First", "Second", "Third"};
try {
socket = new Socket(serverIP, port);
os = socket.getOutputStream();
is = socket.getInputStream();
byte[] b = new byte[1024];
for (int i = 0; i < data.length; i++) {
os.write(data[i].getBytes());
int n = is.read(b);
System.out.println("服務器回饋:" + new String(b, 0, n));
}
} catch (Exception e) { e.printStackTrace(); }
finally {
try { is.close(); os.close(); socket.close(); } catch (Exception e2) {}
}
}
}

for 循環順序發送三條數據。若搭配原版服務端(單次交換後關閉),客戶端第二次發送會拋出 SocketException: Software caused connection abort,因服務端已關閉連接。

服務端復用示例

package tcp;
import java.io.*;
import java.net.*;

public class MulSocketServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
OutputStream os = null;
InputStream is = null;
int port = 10000;
try {
serverSocket = new ServerSocket(port);
System.out.println("服務器已啟動:");
socket = serverSocket.accept();
is = socket.getInputStream();
os = socket.getOutputStream();
byte[] b = new byte[1024];
for (int i = 0; i < 3; i++) {
int n = is.read(b);
System.out.println("客戶端發送內容為:" + new String(b, 0, n));
os.write(b, 0, n);
}
} catch (Exception e) { e.printStackTrace(); }
finally {
try { os.close(); is.close(); socket.close(); serverSocket.close(); } catch (Exception e) {}
}
}
}

服務端也用 for 循環固定 3 次交換。運行結果體現「請求-響應」模型:客戶端發 First → 服務端輸出並回饋 First → 客戶端輸出回饋 → 繼續 Second、Third。

但此硬編碼次數不靈活。若客戶端次數不固定,可用特殊字符串(如 "quit")作為結束標誌,這涉及協議設計,後續詳述。

二、如何使服務端支援多客戶端並發?

概念級服務端離實用尚遠,核心問題是支援多客戶端同時工作。解決方案:接收連接時啟動專用線程處理該連接。

多線程服務端架構

由兩部分組成:

  • MulThreadSocketServer:控制類,監聽端口,接受連接,啟動邏輯線程。
  • LogicThread:處理單一客戶端連接邏輯,run 方法中實現交互。

控制類代碼

package tcp;
import java.net.ServerSocket;
import java.net.Socket;

public class MulThreadSocketServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
int port = 10000;
try {
serverSocket = new ServerSocket(port);
System.out.println("服務器已啟動:");
while (true) {
socket = serverSocket.accept();
new LogicThread(socket);
}
} catch (Exception e) { e.printStackTrace(); }
finally {
try { serverSocket.close(); } catch (Exception e) {}
}
}
}

while 真死循環,accept 阻塞等待連接。連接到達 → 接受 → 啟動 LogicThread → 繼續等待下一連接。多線程支撐多客戶端並發。

邏輯線程代碼

package tcp;
import java.io.*;
import java.net.*;

public class LogicThread extends Thread {
Socket socket;
InputStream is;
OutputStream os;

public LogicThread(Socket socket) {
this.socket = socket;
start();
}

public void run() {
byte[] b = new byte[1024];
try {
os = socket.getOutputStream();
is = socket.getInputStream();
for (int i = 0; i < 3; i++) {
int n = is.read(b);
byte[] response = logic(b, 0, n);
os.write(response);
}
} catch (Exception e) { e.printStackTrace(); }
finally { close(); }
}

private void close() {
try { os.close(); is.close(); socket.close(); } catch (Exception e) {}
}

private byte[] logic(byte[] b, int off, int len) {
byte[] response = new byte[len];
System.arraycopy(b, 0, response, 0, len);
return response;
}
}

構造時傳入連接對象並啟動。run 方法初始化流,循環 3 次讀取數據,調用 logic 方法(echo 邏輯:原樣返回有效數據),寫入輸出流。logic 封裝邏輯,參數為緩衝區、起始下標、有效長度。

線程池優化

實際生產中,受硬體與端口數限制,不能無限創建線程,且頻繁創建銷毀效率低。採用線程池:啟動時預創建固定數量線程(如 5000 個),連接到達從池取用,斷開後歸還池中復用,提升速度優化內存佔用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved