最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?Socket編程從零到實戰(zhàn)詳解(完整實戰(zhàn)案例)

 更新時間:2025年04月12日 10:06:42   作者:北嶺敲鍵盤的荒漠貓  
這篇文章主要介紹了Java?Socket編程從零到實戰(zhàn)詳解,本文給大家介紹的非常詳細,感興趣的朋友一起看看吧

一、Socket基礎(chǔ)概念與工作流程(圖解)

(先理解“打電話”模型,再寫代碼)

1. Socket通信核心模型

關(guān)鍵角色

  • 客戶端:主動發(fā)起連接(類似撥打電話)
  • 服務(wù)端:監(jiān)聽端口,等待連接(類似待機電話)
  • Socket對象:連接建立后的數(shù)據(jù)傳輸通道(通話線路)

2. 核心流程分解

  • 服務(wù)端:創(chuàng)建ServerSocket → 綁定端口 → 阻塞等待連接(accept()
  • 客戶端:創(chuàng)建Socket → 指定服務(wù)端IP和端口 → 發(fā)起連接
  • 雙向通信:通過輸入流(InputStream)和輸出流(OutputStream)收發(fā)數(shù)據(jù)
  • 關(guān)閉連接:調(diào)用close()釋放資源

二、服務(wù)端與客戶端基礎(chǔ)代碼分步解析

(每行代碼加注釋,新手必看)

1. 服務(wù)端基礎(chǔ)代碼(單線程版)

// 步驟1:創(chuàng)建ServerSocket,綁定端口8080
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服務(wù)端啟動,等待連接...");
// 步驟2:等待客戶端連接(阻塞方法,直到有客戶端連接)
Socket clientSocket = serverSocket.accept(); 
System.out.println("客戶端接入:" + clientSocket.getRemoteSocketAddress());
// 步驟3:獲取輸入流(接收客戶端數(shù)據(jù))
InputStream input = clientSocket.getInputStream();
byte[] buffer = new byte[1024];
int len = input.read(buffer);  // 讀取數(shù)據(jù)到buffer數(shù)組
String receivedData = new String(buffer, 0, len);
System.out.println("收到消息:" + receivedData);
// 步驟4:發(fā)送響應(yīng)數(shù)據(jù)
OutputStream output = clientSocket.getOutputStream();
output.write("已收到!".getBytes());
// 步驟5:關(guān)閉連接(實際開發(fā)中需在finally塊處理)
clientSocket.close();
serverSocket.close();

2. 客戶端基礎(chǔ)代碼

// 步驟1:連接服務(wù)端(IP+端口)
Socket socket = new Socket("127.0.0.1", 8080);
System.out.println("連接服務(wù)端成功!");
// 步驟2:發(fā)送數(shù)據(jù)
OutputStream output = socket.getOutputStream();
output.write("你好,服務(wù)端!".getBytes());
// 步驟3:接收響應(yīng)
InputStream input = socket.getInputStream();
byte[] buffer = new byte[1024];
int len = input.read(buffer);
String response = new String(buffer, 0, len);
System.out.println("服務(wù)端響應(yīng):" + response);
// 步驟4:關(guān)閉連接
socket.close();

三、超時設(shè)置詳解(解決卡死問題)

(必學技能,避免程序無限等待)

1. 連接超時(防止無法連接時卡死)

Socket socket = new Socket();
// 設(shè)置連接超時為5秒(單位:毫秒)
socket.connect(new InetSocketAddress("127.0.0.1", 8080), 5000);  // 
  • 觸發(fā)場景:服務(wù)端未啟動或網(wǎng)絡(luò)不通
  • 異常處理:捕獲SocketTimeoutException提示用戶檢查網(wǎng)絡(luò)

2. 讀取超時(防止數(shù)據(jù)未到達時阻塞)

socket.setSoTimeout(3000);  // 設(shè)置讀取超時3秒 
  • 作用范圍InputStream.read()操作
  • 異常處理:超時后拋出SocketTimeoutException,可重試或終止

3. 完整超時處理示例

try (Socket socket = new Socket()) {
    // 連接超時5秒
    socket.connect(new InetSocketAddress("127.0.0.1", 8080), 5000);
    // 讀取超時3秒
    socket.setSoTimeout(3000);
    InputStream input = socket.getInputStream();
    // 讀取數(shù)據(jù)...
} catch (SocketTimeoutException e) {
    System.err.println("操作超時:" + e.getMessage());
} catch (IOException e) {
    System.err.println("連接失?。? + e.getMessage());
}

四、心跳機制實現(xiàn)(維持長連接)

(防止長時間無數(shù)據(jù)導致連接斷開)

1. 心跳包原理

  • 作用:定時發(fā)送空數(shù)據(jù)包,告知對方連接存活
  • 實現(xiàn)方式:客戶端定時任務(wù) + 服務(wù)端超時檢測

2. 客戶端心跳代碼

Timer timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        try {
            OutputStream out = socket.getOutputStream();
            out.write(0);  // 發(fā)送心跳包(內(nèi)容可為任意約定標識)
            out.flush();
            System.out.println("心跳發(fā)送成功");
        } catch (IOException e) {
            System.err.println("心跳發(fā)送失敗,連接已斷開");
            timer.cancel();  // 停止定時任務(wù)
        }
    }
}, 0, 30000);  // 立即啟動,每30秒執(zhí)行一次 

3. 服務(wù)端檢測心跳

socket.setSoTimeout(45000);  // 超時時間略大于心跳間隔
try {
    InputStream in = socket.getInputStream();
    while (true) {
        int data = in.read();  // 阻塞等待數(shù)據(jù)
        if (data == 0) {
            System.out.println("收到心跳包");
        }
    }
} catch (SocketTimeoutException e) {
    System.err.println("心跳超時,連接斷開");
    socket.close();
}

五、完整實戰(zhàn)案例:帶超時與心跳的Echo服務(wù)

服務(wù)端代碼(多線程版)

public class EchoServer {
    public static void main(String[] args) throws IOException {
        ExecutorService pool = Executors.newCachedThreadPool();  // 線程池處理并發(fā)
        try (ServerSocket server = new ServerSocket(8080)) {
            System.out.println("服務(wù)端啟動,端口8080");
            while (true) {
                Socket client = server.accept();
                client.setSoTimeout(45000);  // 設(shè)置讀取超時45秒 
                pool.submit(() -> handleClient(client));
            }
        }
    }
    private static void handleClient(Socket client) {
        try (BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
             PrintWriter out = new PrintWriter(client.getOutputStream(), true)) {
            String input;
            while ((input = in.readLine()) != null) {
                if ("HEARTBEAT".equals(input)) {  // 識別心跳包
                    System.out.println("收到心跳包");
                    continue;
                }
                out.println("Echo: " + input);  // 回顯消息
            }
        } catch (SocketTimeoutException e) {
            System.err.println("客戶端超時未響應(yīng),連接關(guān)閉");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try { client.close(); } catch (IOException e) {}
        }
    }
}

客戶端代碼(帶心跳與超時)

public class EchoClient {
    public static void main(String[] args) {
        try (Socket socket = new Socket()) {
            // 連接超時5秒
            socket.connect(new InetSocketAddress("127.0.0.1", 8080), 5000);
            // 讀取超時3秒
            socket.setSoTimeout(3000);
            // 啟動心跳線程(每30秒一次)
            startHeartbeat(socket.getOutputStream());
            Scanner scanner = new Scanner(System.in);
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
            BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            while (true) {
                System.out.print("輸入消息:");
                String msg = scanner.nextLine();
                out.println(msg);  // 發(fā)送消息
                System.out.println("服務(wù)端響應(yīng):" + in.readLine());
            }
        } catch (SocketTimeoutException e) {
            System.err.println("操作超時:" + e.getMessage());
        } catch (IOException e) {
            System.err.println("連接異常:" + e.getMessage());
        }
    }
    private static void startHeartbeat(OutputStream out) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
                    out.write("HEARTBEAT\n".getBytes());  // 發(fā)送心跳標識
                    out.flush();
                } catch (IOException e) {
                    timer.cancel();
                }
            }
        }, 0, 30000);
    }
}

六、常見問題與解決方案速查表

問題現(xiàn)象可能原因解決方案
Connection refused服務(wù)端未啟動或端口錯誤檢查服務(wù)端代碼是否運行,確認端口一致
Read timed out網(wǎng)絡(luò)延遲或服務(wù)端未及時響應(yīng)增加超時時間或優(yōu)化服務(wù)端代碼
Broken pipe連接已關(guān)閉仍嘗試寫數(shù)據(jù)發(fā)送前檢查socket.isClosed(),捕獲異常后重連
內(nèi)存泄漏未關(guān)閉Socket或流使用try-with-resources自動關(guān)閉資源

七、Java Socket核心方法速查表

方法名所屬類功能描述參數(shù)說明返回值常見異常使用示例
ServerSocket(int port)ServerSocket創(chuàng)建服務(wù)端Socket并綁定指定端口port:監(jiān)聽的端口號(0-65535)BindException(端口被占用)new ServerSocket(8080);
accept()ServerSocket阻塞等待客戶端連接,返回通信用的Socket對象Socket(客戶端連接對象)IOExceptionSocket client = serverSocket.accept();
close()ServerSocket關(guān)閉服務(wù)端Socket,釋放端口資源IOExceptionserverSocket.close();
Socket(String host, int port)Socket客戶端主動連接服務(wù)端(構(gòu)造函數(shù)隱式調(diào)用connect()host:服務(wù)端IP;port:服務(wù)端端口UnknownHostException, IOExceptionSocket socket = new Socket("127.0.0.1", 8080);
connect(SocketAddress addr, int timeout)Socket顯式連接服務(wù)端,可設(shè)置超時時間addr:服務(wù)端地址;timeout:超時毫秒SocketTimeoutExceptionsocket.connect(new InetSocketAddress("127.0.0.1", 8080), 5000);
getInputStream()Socket獲取輸入流,用于接收數(shù)據(jù)InputStreamIOExceptionInputStream in = socket.getInputStream();
getOutputStream()Socket獲取輸出流,用于發(fā)送數(shù)據(jù)OutputStreamIOExceptionOutputStream out = socket.getOutputStream();
setSoTimeout(int timeout)Socket設(shè)置讀取超時時間(單位:毫秒),超時后拋出SocketTimeoutExceptiontimeout:超時時間(0表示無限等待)SocketExceptionsocket.setSoTimeout(3000);
setKeepAlive(boolean on)Socket啟用/禁用TCP保活機制(默認關(guān)閉),自動檢測連接是否存活on:true啟用,false禁用SocketExceptionsocket.setKeepAlive(true);
shutdownOutput()Socket關(guān)閉輸出流(發(fā)送FIN包),通知對方數(shù)據(jù)發(fā)送完畢,但不關(guān)閉SocketIOExceptionsocket.shutdownOutput();
close()Socket關(guān)閉Socket連接,釋放資源IOExceptionsocket.close();
readInt()DataInputStream從輸入流讀取4字節(jié)的int值(常用于解析長度頭)intEOFException, IOExceptionint length = new DataInputStream(in).readInt();
writeInt(int v)DataOutputStream向輸出流寫入4字節(jié)的int值(常用于發(fā)送長度頭)v:要寫入的整數(shù)值IOExceptionnew DataOutputStream(out).writeInt(1024);

到此這篇關(guān)于Java Socket編程從零到實戰(zhàn)詳解的文章就介紹到這了,更多相關(guān)Java Socket編程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Boot如何使用JDBC獲取相關(guān)的數(shù)據(jù)詳解

    Spring Boot如何使用JDBC獲取相關(guān)的數(shù)據(jù)詳解

    這篇文章主要給大家介紹了關(guān)于Spring Boot如何使用JDBC獲取相關(guān)數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-03-03
  • Java實現(xiàn)線程同步方法及原理詳解

    Java實現(xiàn)線程同步方法及原理詳解

    這篇文章主要介紹了Java實現(xiàn)線程同步方法及原理詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能

    Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能

    IO 是基于流來讀取的,而NIO則是基于塊讀取,面向流 的 I/O 系統(tǒng)一次一個字節(jié)地處理數(shù)據(jù),這篇文章主要介紹了Java使用NIO優(yōu)化IO實現(xiàn)文件上傳下載功能,需要的朋友可以參考下
    2022-07-07
  • 如何使用java.security.SecureRandom安全生成隨機數(shù)和隨機字符串工具類

    如何使用java.security.SecureRandom安全生成隨機數(shù)和隨機字符串工具類

    這篇文章主要給大家介紹了關(guān)于如何使用java.security.SecureRandom安全生成隨機數(shù)和隨機字符串工具類的相關(guān)資料,SecureRandom擴展了Random類,并通過在java 8中添加的新方法得到了豐富,需要的朋友可以參考下
    2024-05-05
  • Redis應(yīng)用問題及分布式鎖使用說明

    Redis應(yīng)用問題及分布式鎖使用說明

    文章主要討論了緩存穿透、緩存雪崩和分布式鎖在高并發(fā)場景下的解決方案,包括對空值緩存、設(shè)置白名單、布隆過濾器監(jiān)控、預(yù)先設(shè)置熱門數(shù)據(jù)、實時調(diào)整過期時間、使用鎖機制以及構(gòu)建多級緩存架構(gòu)等
    2026-03-03
  • intellij idea14打包apk文件和查看sha1值

    intellij idea14打包apk文件和查看sha1值

    這篇文章主要為大家詳細介紹了intellij idea14打包apk文件和查看sha1值,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-10-10
  • Java Ehcache緩存框架入門級使用實例

    Java Ehcache緩存框架入門級使用實例

    這篇文章主要介紹了Java Ehcache緩存框架入門級使用實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-08-08
  • springboot整合mybatis的超詳細過程(配置模式+注解模式)

    springboot整合mybatis的超詳細過程(配置模式+注解模式)

    這篇文章主要介紹了springboot整合mybatis的詳細過程(配置模式+注解模式),這里我使用的是配置模式+注解模式所以需要配置全局文件,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • CentOS8.2安裝Java 14.0.2的教程詳解

    CentOS8.2安裝Java 14.0.2的教程詳解

    這篇文章主要介紹了CentOS8.2安裝Java 14.0.2的詳細教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui詳解

    Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui詳解

    這篇文章主要介紹了Mybatis-Plus開發(fā)提速器mybatis-plus-generator-ui,本文簡要介紹一款基于Mybatis-Plus的代碼自助生成器,文章通過實例集成的方式來詳細講解mybatis-plus-generator-ui,從相關(guān)概念到實際集成案例,以及具體的擴展開發(fā)介紹,需要的朋友可以參考下
    2022-11-11

最新評論

合山市| 宝鸡市| 日照市| 建阳市| 高台县| 博爱县| 大理市| 呈贡县| 长寿区| 宣武区| 呼图壁县| 资兴市| 石城县| 武功县| 疏勒县| 额尔古纳市| 浦北县| 浙江省| 新闻| 兴隆县| 岳池县| 昭通市| 福鼎市| 崇礼县| 年辖:市辖区| 嘉祥县| 全南县| 大同县| 霍城县| 定边县| 陇南市| 武汉市| 成武县| 盈江县| 西青区| 尼勒克县| 西华县| 红河县| 柏乡县| 东海县| 民乐县|