Java?網(wǎng)絡(luò)編程TCP、UDP、HTTP、WebSocket全解
Java 網(wǎng)絡(luò)編程核心是基于 Socket 實現(xiàn)傳輸層通信(TCP/UDP),基于標(biāo)準(zhǔn)庫 / 框架實現(xiàn)應(yīng)用層協(xié)議(HTTP/WebSocket),覆蓋基礎(chǔ)通信、生產(chǎn)環(huán)境高可用、并發(fā)、異常處理、資源釋放等全場景。
一、核心基礎(chǔ)概念
- TCP:面向連接、可靠、有序、字節(jié)流傳輸(如:文件傳輸、接口調(diào)用)
- UDP:無連接、不可靠、快速、數(shù)據(jù)報傳輸(如:直播、實時消息)
- HTTP:應(yīng)用層協(xié)議,基于 TCP,短連接 / 長連接(Web 接口、網(wǎng)頁)
- WebSocket:基于 TCP 的全雙工長連接,解決 HTTP 輪詢弊端(實時通信)
- Socket:Java 網(wǎng)絡(luò)編程的基石,是IP + 端口的抽象,分為:
ServerSocket:服務(wù)端,監(jiān)聽端口等待連接Socket:客戶端,主動發(fā)起連接
代碼概括:
二、傳輸層編程:TCP(生產(chǎn)級)
基礎(chǔ)原理
- 三次握手建立連接,四次揮手?jǐn)嚅_
- 可靠傳輸:超時重傳、擁塞控制、順序保證
- 適合:需要數(shù)據(jù)不丟失、不亂序的場景
生產(chǎn)級 TCP 服務(wù)端(線程池 + 心跳 + 優(yōu)雅關(guān)閉)
核心優(yōu)化:
- 線程池異步處理客戶端,避免單線程阻塞
- 心跳機制檢測死連接
- 優(yōu)雅關(guān)閉:釋放端口、關(guān)閉線程池、中斷線程
- 全局異常捕獲 + 日志
- 配置化端口、超時時間
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* 生產(chǎn)級 TCP 服務(wù)端
*/
public class TcpServer {
private static final Logger log = LoggerFactory.getLogger(TcpServer.class);
// 配置化參數(shù)(可抽取到配置文件)
private static final int PORT = 9999;
private static final int SO_TIMEOUT = 30000; // 30秒無心跳斷開
private static final int CORE_POOL_SIZE = 10;
private final ExecutorService threadPool = Executors.newFixedThreadPool(CORE_POOL_SIZE);
private ServerSocket serverSocket;
private volatile boolean isRunning = true;
public static void main(String[] args) {
new TcpServer().start();
}
/**
* 啟動服務(wù)端
*/
public void start() {
try {
serverSocket = new ServerSocket(PORT);
log.info("TCP 服務(wù)端啟動成功,端口:{}", PORT);
// 注冊優(yōu)雅關(guān)閉鉤子
Runtime.getRuntime().addShutdownHook(new Thread(this::shutdown));
while (isRunning) {
// 阻塞等待客戶端連接
Socket clientSocket = serverSocket.accept();
log.info("客戶端連接成功:{}:{}", clientSocket.getInetAddress(), clientSocket.getPort());
// 線程池處理客戶端請求
threadPool.execute(new ClientHandler(clientSocket));
}
} catch (Exception e) {
if (isRunning) {
log.error("TCP 服務(wù)端異常", e);
}
}
}
/**
* 優(yōu)雅關(guān)閉
*/
public void shutdown() {
try {
isRunning = false;
if (serverSocket != null && !serverSocket.isClosed()) {
serverSocket.close();
}
threadPool.shutdown();
if (!threadPool.awaitTermination(5, TimeUnit.SECONDS)) {
threadPool.shutdownNow();
}
log.info("TCP 服務(wù)端已優(yōu)雅關(guān)閉");
} catch (Exception e) {
log.error("服務(wù)端關(guān)閉異常", e);
}
}
/**
* 客戶端處理器(生產(chǎn)級:心跳、異常處理、資源釋放)
*/
private static class ClientHandler implements Runnable {
private final Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
public ClientHandler(Socket socket) {
this.socket = socket;
try {
socket.setSoTimeout(SO_TIMEOUT); // 讀超時(心跳檢測)
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (Exception e) {
close();
}
}
@Override
public void run() {
try {
String msg;
while ((msg = reader.readLine()) != null) {
log.info("收到客戶端消息:{}", msg);
// 心跳包處理
if ("heartbeat".equals(msg)) {
sendMsg("heartbeat_ack");
continue;
}
// 業(yè)務(wù)消息處理
String resp = "服務(wù)端已接收:" + msg;
sendMsg(resp);
}
} catch (Exception e) {
log.warn("客戶端連接異常:{}", e.getMessage());
} finally {
close();
}
}
/**
* 發(fā)送消息
*/
private void sendMsg(String msg) throws IOException {
writer.write(msg + "\n");
writer.flush();
}
/**
* 統(tǒng)一釋放資源
*/
private void close() {
try {
if (reader != null) reader.close();
if (writer != null) writer.close();
if (socket != null && !socket.isClosed()) socket.close();
log.info("客戶端連接已關(guān)閉:{}:{}", socket.getInetAddress(), socket.getPort());
} catch (Exception e) {
log.error("資源釋放異常", e);
}
}
}
}生產(chǎn)級 TCP 客戶端(重連 + 心跳 + 異步發(fā)送)
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
import java.net.Socket;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 生產(chǎn)級 TCP 客戶端(自動重連+心跳)
*/
public class TcpClient {
private static final Logger log = LoggerFactory.getLogger(TcpClient.class);
private static final String SERVER_HOST = "127.0.0.1";
private static final int SERVER_PORT = 9999;
private static final int HEARTBEAT_INTERVAL = 5; // 5秒心跳
private static final int RECONNECT_INTERVAL = 3; // 3秒重連
private Socket socket;
private BufferedReader reader;
private BufferedWriter writer;
private volatile boolean isConnected = false;
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static void main(String[] args) {
TcpClient client = new TcpClient();
client.connect();
// 測試發(fā)送消息
client.sendMsg("Hello TCP Server");
}
/**
* 建立連接(失敗自動重連)
*/
public void connect() {
while (!isConnected) {
try {
socket = new Socket(SERVER_HOST, SERVER_PORT);
reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
isConnected = true;
log.info("連接服務(wù)端成功");
// 啟動心跳
startHeartbeat();
// 監(jiān)聽服務(wù)端消息
new Thread(this::listenServerMsg).start();
} catch (Exception e) {
log.error("連接失敗,{}秒后重試...", RECONNECT_INTERVAL);
try {
TimeUnit.SECONDS.sleep(RECONNECT_INTERVAL);
} catch (InterruptedException ignored) {}
}
}
}
/**
* 心跳機制
*/
private void startHeartbeat() {
scheduler.scheduleAtFixedRate(() -> {
try {
if (isConnected) {
sendMsg("heartbeat");
log.debug("發(fā)送心跳包");
}
} catch (Exception e) {
log.error("心跳異常,開始重連");
disconnect();
connect();
}
}, 0, HEARTBEAT_INTERVAL, TimeUnit.SECONDS);
}
/**
* 監(jiān)聽服務(wù)端消息
*/
private void listenServerMsg() {
try {
String msg;
while ((msg = reader.readLine()) != null) {
log.info("收到服務(wù)端消息:{}", msg);
}
} catch (Exception e) {
log.warn("與服務(wù)端斷開連接");
disconnect();
connect();
}
}
/**
* 發(fā)送消息(線程安全)
*/
public synchronized void sendMsg(String msg) {
if (!isConnected) {
log.warn("未連接服務(wù)端,消息發(fā)送失?。簕}", msg);
return;
}
try {
writer.write(msg + "\n");
writer.flush();
} catch (Exception e) {
log.error("消息發(fā)送異常", e);
disconnect();
connect();
}
}
/**
* 斷開連接
*/
private void disconnect() {
isConnected = false;
try {
if (reader != null) reader.close();
if (writer != null) writer.close();
if (socket != null) socket.close();
} catch (Exception ignored) {}
}
}三、傳輸層編程:UDP(生產(chǎn)級)
基礎(chǔ)原理
- 無連接,直接發(fā)送數(shù)據(jù)報
- 速度快,不保證可靠
- 適合:實時性要求高、可容忍少量丟包的場景
生產(chǎn)級 UDP 服務(wù)端 + 客戶端
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 生產(chǎn)級 UDP(服務(wù)端+客戶端合一)
*/
public class UdpServerClient {
private static final Logger log = LoggerFactory.getLogger(UdpServerClient.class);
private static final int PORT = 9998;
private static final int BUFFER_SIZE = 1024;
private final ExecutorService threadPool = Executors.newSingleThreadExecutor();
public static void main(String[] args) {
UdpServerClient udp = new UdpServerClient();
udp.startServer();
udp.sendClientMsg("127.0.0.1", "Hello UDP Server");
}
// ==================== UDP 服務(wù)端 ====================
public void startServer() {
threadPool.execute(() -> {
try (DatagramSocket socket = new DatagramSocket(PORT)) {
log.info("UDP 服務(wù)端啟動,端口:{}", PORT);
byte[] buffer = new byte[BUFFER_SIZE];
while (true) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet); // 阻塞接收
String msg = new String(packet.getData(), 0, packet.getLength());
log.info("收到UDP消息:{} 來自:{}:{}",
msg, packet.getAddress(), packet.getPort());
// 回寫消息
String resp = "UDP 已接收:" + msg;
sendUdpMsg(socket, packet.getAddress(), packet.getPort(), resp);
}
} catch (Exception e) {
log.error("UDP 服務(wù)端異常", e);
}
});
}
// ==================== UDP 客戶端發(fā)送 ====================
public void sendClientMsg(String host, String msg) {
try (DatagramSocket socket = new DatagramSocket()) {
InetAddress address = InetAddress.getByName(host);
sendUdpMsg(socket, address, PORT, msg);
log.info("UDP 客戶端發(fā)送消息:{}", msg);
} catch (Exception e) {
log.error("UDP 客戶端發(fā)送異常", e);
}
}
/**
* 統(tǒng)一發(fā)送 UDP 消息
*/
private void sendUdpMsg(DatagramSocket socket, InetAddress addr, int port, String msg) throws Exception {
byte[] data = msg.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, addr, port);
socket.send(packet);
}
}四、應(yīng)用層編程:HTTP(生產(chǎn)級)
Java 生產(chǎn)環(huán)境絕不使用原生 HttpURLConnection,推薦兩款標(biāo)準(zhǔn)框架:
- OkHttp:輕量、穩(wěn)定、Android / 后端通用
- RestTemplate:Spring 生態(tài)標(biāo)準(zhǔn)(微服務(wù)首選)
1. OkHttp 生產(chǎn)級 HTTP 工具類
依賴:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>生產(chǎn)級代碼(連接池、超時、重試、單例):
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.TimeUnit;
/**
* 生產(chǎn)級 OkHttp 工具類(單例+連接池)
*/
public class OkHttpUtil {
private static final Logger log = LoggerFactory.getLogger(OkHttpUtil.class);
private static final OkHttpClient CLIENT;
private static final int MAX_IDLE_CONNECTIONS = 20;
private static final long KEEP_ALIVE_DURATION = 5L;
// 單例 OkHttpClient(關(guān)鍵:OkHttp 必須單例,復(fù)用連接池)
static {
CLIENT = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(MAX_IDLE_CONNECTIONS, KEEP_ALIVE_DURATION, TimeUnit.MINUTES))
.retryOnConnectionFailure(true) // 自動重試
.build();
}
private OkHttpUtil() {}
/**
* GET 請求
*/
public static String get(String url) throws Exception {
Request request = new Request.Builder()
.url(url)
.addHeader("Content-Type", "application/json")
.build();
try (Response response = CLIENT.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new Exception("HTTP 請求失敗,狀態(tài)碼:" + response.code());
}
return response.body().string();
}
}
/**
* POST JSON 請求
*/
public static String postJson(String url, String json) throws Exception {
RequestBody body = RequestBody.create(json, MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = CLIENT.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new Exception("HTTP POST 失敗,狀態(tài)碼:" + response.code());
}
return response.body().string();
}
}
}2. Spring RestTemplate 生產(chǎn)級配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* Spring 生產(chǎn)級 RestTemplate 配置
*/
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
return new RestTemplate(factory);
}
@Bean
public ClientHttpRequestFactory clientHttpRequestFactory() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(10000);
// 生產(chǎn)環(huán)境可替換為 OkHttp 工廠,性能更強
return factory;
}
}五、應(yīng)用層編程:WebSocket(生產(chǎn)級)
基礎(chǔ)原理
- 基于 TCP,全雙工長連接
- 一次握手,永久通信,服務(wù)端可主動推送消息
- 適合:聊天、實時通知、大屏數(shù)據(jù)
Spring Boot 生產(chǎn)級 WebSocket
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>生產(chǎn)級代碼(集群可配合 Redis 廣播):
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 生產(chǎn)級 WebSocket 服務(wù)端
*/
@Component
@ServerEndpoint("/ws/server")
public class WebSocketServer {
private static final Logger log = LoggerFactory.getLogger(WebSocketServer.class);
// 在線連接數(shù)(線程安全)
private static final AtomicInteger ONLINE_COUNT = new AtomicInteger(0);
// 客戶端集合(線程安全)
private static final CopyOnWriteArraySet<WebSocketServer> WEB_SOCKET_SET = new CopyOnWriteArraySet<>();
private Session session;
/**
* 連接建立成功
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
WEB_SOCKET_SET.add(this);
ONLINE_COUNT.incrementAndGet();
log.info("新連接加入,當(dāng)前在線:{}", ONLINE_COUNT.get());
sendMessage("連接成功");
}
/**
* 連接關(guān)閉
*/
@OnClose
public void onClose() {
WEB_SOCKET_SET.remove(this);
ONLINE_COUNT.decrementAndGet();
log.info("連接關(guān)閉,當(dāng)前在線:{}", ONLINE_COUNT.get());
}
/**
* 收到客戶端消息
*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到消息:{}", message);
// 群發(fā)消息
sendToAll("服務(wù)端廣播:" + message);
}
/**
* 異常處理
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("WebSocket 異常", error);
}
/**
* 發(fā)送消息
*/
public void sendMessage(String message) {
try {
this.session.getBasicRemote().sendText(message);
} catch (Exception e) {
log.error("消息發(fā)送失敗", e);
}
}
/**
* 群發(fā)消息(生產(chǎn)常用)
*/
public static void sendToAll(String message) {
for (WebSocketServer ws : WEB_SOCKET_SET) {
ws.sendMessage(message);
}
}
}啟用 WebSocket:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
@SpringBootApplication
@EnableWebSocket // 開啟 WebSocket
public class NettyApplication {
public static void main(String[] args) {
SpringApplication.run(NettyApplication.class, args);
}
}六、生產(chǎn)環(huán)境核心最佳實踐(必看)
- Socket 必須單例 / 池化
- TCP 客戶端、OkHttp、RestTemplate 禁止頻繁創(chuàng)建對象,必須復(fù)用連接池
- 超時強制設(shè)置
- 連接超時、讀超時、寫超時,避免線程無限阻塞
- 優(yōu)雅關(guān)閉
- 用
shutdownHook釋放端口、線程池、Socket,防止端口占用
- 用
- 心跳機制
- TCP/WebSocket 必須加心跳,檢測死連接,釋放資源
- 線程池替代多線程
- 禁止為每個客戶端創(chuàng)建新線程,用線程池控制并發(fā)
- 異常全覆蓋
- IO 異常、連接異常、超時異常必須捕獲,不能直接拋出
- 生產(chǎn)禁用原生 Socket 高并發(fā)場景
- 高并發(fā)用 Netty(NIO 框架),性能提升 10~100 倍
由以上可總結(jié)出:
- 傳輸層:TCP 可靠(生產(chǎn)用線程池 + 心跳),UDP 快速(實時場景)
- 應(yīng)用層:HTTP 用 OkHttp/RestTemplate,WebSocket 用 Spring 封裝
- 生產(chǎn)核心:連接池、超時、優(yōu)雅關(guān)閉、心跳、異常處理
- 高并發(fā)方案:原生 Socket 僅適合小并發(fā),高并發(fā)必須用 Netty
概念概括
一 Java 網(wǎng)絡(luò)編程本質(zhì)就是兩層:
- 傳輸層(TCP、UDP)
- 基于 Socket 編程
- 自己定義報文格式、粘包拆包、心跳、重連
- 應(yīng)用層(HTTP、HTTPS、WebSocket)
- 基于 TCP 封裝好的協(xié)議
- 不用關(guān)心底層連接,只關(guān)心請求 / 響應(yīng)
二、TCP、UDP、HTTP、WebSocket 核心區(qū)別對比表
| 對比項 | TCP | UDP | HTTP | WebSocket |
|---|---|---|---|---|
| 連接方式 | 面向連接(三次握手) | 無連接 | 基于 TCP,短 / 長連接 | 基于 TCP,全雙工長連接 |
| 可靠性 | 可靠,不丟包、不亂序 | 不可靠,可能丟包、亂序 | 可靠(依賴 TCP) | 可靠(依賴 TCP) |
| 傳輸方式 | 字節(jié)流 | 數(shù)據(jù)報 | 請求 - 響應(yīng)模型 | 全雙工,雙向主動推送 |
| 開銷 | 高(握手、確認(rèn)、重傳) | 低 | 很高(Header 大) | 中等(握手一次,后續(xù)幀很小) |
| 速度 | 較慢 | 極快 | 慢 | 快 |
| 消息邊界 | 無邊界 → 粘包拆包問題 | 有邊界 → 不會粘包 | 協(xié)議自帶邊界 | 幀結(jié)構(gòu),自帶邊界 |
| 服務(wù)端推送 | 需自己實現(xiàn) | 需自己實現(xiàn) | 不能主動推送 | 支持主動推送 |
| 典型用途 | 文件傳輸、IM、支付、長連接 | 直播、語音、游戲、DNS | 接口、網(wǎng)頁、RESTful | 聊天、大屏、實時通知、物聯(lián)網(wǎng) |
1. TCP(Transmission Control Protocol)
特點
- 面向連接,可靠傳輸
- 有序、重傳、流量控制、擁塞控制
- 字節(jié)流傳輸,沒有消息邊界
- 適合對數(shù)據(jù)完整性要求高的場景
生產(chǎn)注意事項(非常重要)
- 必須處理粘包 / 拆包TCP 是流,發(fā)送 2 次數(shù)據(jù)可能被合并成 1 次,或 1 次被拆成多段。解決方案:
- 固定長度
- 分隔符(\n、\r\n)
- 長度域 + 報文體(生產(chǎn)標(biāo)準(zhǔn)方案)
- 必須設(shè)置 SO_TIMEOUT不設(shè)置會導(dǎo)致線程永久阻塞,OOM 或線程耗盡
- 禁止每次 new Socket必須復(fù)用連接、使用連接池
- 必須心跳?;?/strong>NAT 超時、防火墻會靜默斷開連接,應(yīng)用層無感知
- 必須優(yōu)雅關(guān)閉close () 要放在 finally,避免端口 TIME_WAIT 堆積
- 高并發(fā)不能用 BIO并發(fā) > 100 必須用 NIO / Netty,否則線程爆炸
2. UDP(User Datagram Protocol)
特點
- 無連接,不握手,直接發(fā)
- 數(shù)據(jù)報模式,自帶消息邊界
- 速度極快,開銷極小
- 不保證到達(dá)、順序、重復(fù)
生產(chǎn)注意事項
- 不適合支付、交易、重要指令丟包就沒了
- 適合實時性 > 可靠性直播、實時游戲、實時監(jiān)控
- 無需處理粘包一個 DatagramPacket 就是一個完整包
- 可以自己實現(xiàn)簡單可靠機制序號 + 確認(rèn) + 重傳(RTP 就是這么干的)
- 包大小不要超過 MTU一般 ≤ 1472 字節(jié),否則會被 IP 層分片,更容易丟包
3. HTTP(HyperText Transfer Protocol)
特點
- 應(yīng)用層協(xié)議,基于 TCP
- 請求 - 響應(yīng)模型:客戶端問,服務(wù)端答
- 無狀態(tài)(需要 Cookie / Token)
- 1.1 支持長連接,2.0 多路復(fù)用
- 文本協(xié)議,可讀性強
生產(chǎn)注意事項
- 不能服務(wù)端主動推送只能輪詢、長輪詢,效率低
- Header 開銷大尤其大量小請求,浪費嚴(yán)重
- 必須使用連接池原生 HttpURLConnection 坑多,生產(chǎn)用 OkHttp / RestTemplate
- 超時三要素必須設(shè)置連接超時、讀取超時、寫入超時
- 重試要謹(jǐn)慎讀接口可以重試,寫接口(POST/PUT)必須保證冪等
- HTTPS 必須使用明文傳輸極易被抓包篡改
4. WebSocket
特點
- 基于 TCP,在 HTTP 握手升級而來
- 全雙工:客戶端 ↔ 服務(wù)端 隨時發(fā)
- 一次握手,永久通道
- 數(shù)據(jù)幀很小,開銷極低
- 服務(wù)端可以主動推送
生產(chǎn)注意事項
- 必須心跳代理、防火墻會斷開空閑連接
- 集群環(huán)境要做會話共享多實例部署時,用 Redis 廣播 / STOMP 消息隊列
- 注意內(nèi)存泄漏Session 要及時清理,關(guān)閉連接必須移除集合
- 避免大文件傳輸不是設(shè)計用來傳文件的
- 鑒權(quán)要在握手階段做不要連接建立后再鑒權(quán)
三、它們之間的關(guān)系(一句話串起來)
- HTTP 是跑在 TCP 上的應(yīng)用協(xié)議
- WebSocket 也是跑在 TCP 上,先用 HTTP 握手,再升級成雙工通道
- TCP/UDP 是底層傳輸,你要自己定義協(xié)議
- HTTP/WebSocket 是現(xiàn)成協(xié)議,開箱即用
四、生產(chǎn)中怎么選擇?(最實用)
- 業(yè)務(wù)接口、微服務(wù)調(diào)用 → HTTP/HTTPS
- IM、實時通知、大屏 → WebSocket
- 自定義長連接、網(wǎng)關(guān)、物聯(lián)網(wǎng) → TCP(Netty)
- 直播、語音、實時游戲 → UDP(可加可靠層)
- DNS、心跳探測 → UDP
到此這篇關(guān)于Java 網(wǎng)絡(luò)編程全解:TCP、UDP、HTTP、WebSocket的文章就介紹到這了,更多相關(guān)Java 網(wǎng)絡(luò)編程全解:TCP、UDP、HTTP、WebSocket內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- java實現(xiàn)TCP socket和UDP socket的實例
- Java簡單實現(xiàn)UDP和TCP的示例
- tcp、udp、ip協(xié)議分析_動力節(jié)點Java學(xué)院整理
- 淺談java的TCP和UDP編程(附實例講解)
- java中TCP/UDP詳細(xì)總結(jié)
- java 基礎(chǔ)知識之網(wǎng)絡(luò)通信(TCP通信、UDP通信、多播以及NIO)總結(jié)
- java注解實現(xiàn)websocket服務(wù)的兩種方式
- Java中使用WebSocket的幾種方式
- Java實現(xiàn)使用Websocket發(fā)送消息詳細(xì)代碼舉例
- 如何在Java中使用WebSocket協(xié)議
相關(guān)文章
springboot整合dubbo設(shè)置全局唯一ID進(jìn)行日志追蹤的示例代碼
這篇文章主要介紹了springboot整合dubbo設(shè)置全局唯一ID進(jìn)行日志追蹤,本文通過圖文示例相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10
Springboot使用Spring Data JPA實現(xiàn)數(shù)據(jù)庫操作
Spring Data JPA 是 Spring 基于 Spring Data 框架、在JPA 規(guī)范的基礎(chǔ)上開發(fā)的一個框架,使用 Spring Data JPA 可以極大地簡化JPA 的寫法,本章我們將詳細(xì)介紹在Springboot中使用 Spring Data JPA 來實現(xiàn)對數(shù)據(jù)庫的操作2021-06-06
Java實現(xiàn)猜數(shù)字小游戲(有次數(shù)限制)
這篇文章主要為大家詳細(xì)介紹了Java實現(xiàn)猜數(shù)字小游戲,有次數(shù)限制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05
java線程池對象ThreadPoolExecutor的深入講解
在我們的開發(fā)中“池”的概念并不罕見,有數(shù)據(jù)庫連接池、線程池、對象池、常量池等等。下面這篇文章主要給大家介紹了關(guān)于java線程池對象ThreadPoolExecutor的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧2018-09-09
java.sql.SQLException問題解決以及注意事項
這篇文章主要給大家介紹了關(guān)于java.sql.SQLException問題解決以及注意事項的相關(guān)資料,這個問題其實很好解決,文中通過圖文將解決的辦法介紹的很詳細(xì),需要的朋友可以參考下2023-07-07
springboot應(yīng)用中靜態(tài)資源訪問與接口請求沖突問題解決
這篇文章主要介紹了springboot應(yīng)用中靜態(tài)資源訪問與接口請求沖突,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-06-06

