跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava

Java TCP 网络编程:从可靠传输到 Socket 实战

讲解 Java TCP 网络编程。首先对比 TCP 与 UDP 的区别,包括连接方式、数据传输模式及可靠性。接着介绍 ServerSocket 和 Socket 的核心 API 及其作用。通过服务端和客户端的实战代码,演示如何利用 InputStream、OutputStream、Scanner 和 PrintWriter 实现数据的读写与响应。服务端使用线程池处理并发连接,避免频繁创建线程的开销,并解释了 ServerSocket 与 Socket 的生命周期管理以避免资源泄露。

晚风叙旧发布于 2026/3/26更新于 2026/8/2325K 浏览
Java TCP 网络编程:从可靠传输到 Socket 实战

Java TCP 网络编程:从可靠传输到 Socket 实战

TCP 与 UDP 的区别与相同点

  1. TCP 是有连接的,UDP 无连接。
  2. TCP 是面向字节流的,UDP 是面向数据报的。
  3. TCP 是可靠传输的,UDP 是不可靠传输的。
  4. TCP 和 UDP 都是全双工的。

连接机制

  • UDP:每次发送数据报都要指定对方的地址(UDP 没有存储这个信息)。
  • TCP:不需要手动指定,内核自动和客户端建立连接(TCP 三次握手)。对于应用程序来说,客户端发起'建立连接',服务器端通过 ServerSocket 获取内核中已建立的连接。

ServerSocket 负责绑定端口号,并通过 accept() 方法将建立好的连接拿过来。如果瞬间有很多连接,类似于生产者消费者模型中的阻塞等待。

ServerSocket 与 Socket API 说明

  • ServerSocket:给服务器使用的类,用来绑定端口号,负责把系统内核里面已经建立好的连接从队列里面拿过来。
  • Socket:既会给服务器使用,也会给客户端使用,通过 socket 对象和客户端进行交互。
  • 这两个类都是用来表示 socket 文件的,抽象了网卡这样的硬件设备。

TCP 服务端实战代码演示

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {
    private ServerSocket serverSocket = null;

    public TcpEchoServer(int serverPort) throws IOException {
        // 利用系统 API 从内核中取到已经建立好的连接
        serverSocket = new ServerSocket(serverPort);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            // 一直不断地从内核里面拿我们已经建立好的连接
            Socket clientSocket = serverSocket.accept();
            
            // 线程池是更好的选择,避免频繁创建和销毁线程的开销
            ExecutorService service = Executors.newCachedThreadPool();
            service.submit(() -> possessCollection(clientSocket));
        }
    }

    public void possessCollection(Socket clientSocket) {
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            Scanner scanner = new Scanner(inputStream);
            while (true) {
                if (!scanner.hasNext()) {
                    System.out.printf("[%s,%d] 客户端下线\n", clientSocket.getInetAddress(), clientSocket.getPort());
                    break;
                }
                String request = scanner.next();
                String response = process(request);
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                printWriter.flush();
                System.out.printf("[%s,%d] req=%s resp=%s\n", clientSocket.getInetAddress(), clientSocket.getPort(), request, response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer = new TcpEchoServer(9090);
        tcpEchoServer.start();
    }
}

资源管理说明

为什么 ServerSocket 对象没有进行 close 操作,而 Socket 对象需要 close?

  • 文件资源泄露:一直频繁申请但是一直不释放会造成泄露。
  • ServerSocket:从头到尾只创建过一次对象,生命周期伴随着进程消失,JVM 会在进程结束时回收,因此不需要特地回收。
  • Socket:每个连接对应一个 Socket 对象,处理完后必须关闭以释放资源。

TCP 客户端实战代码演示

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    private Socket socket = null;

    public TcpEchoClient(String serverIP, int serverPort) throws IOException {
        socket = new Socket(serverIP, serverPort);
    }

    public void start() {
        System.out.println("->");
        Scanner scanner = new Scanner(System.in);
        try (OutputStream outputStream = socket.getOutputStream();
             InputStream inputStream = socket.getInputStream()) {
            while (true) {
                String request = scanner.next();
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(request);
                printWriter.flush();
                
                Scanner scannerNetwork = new Scanner(inputStream);
                String response = scannerNetwork.next();
                System.out.println(response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1", 9090);
        tcpEchoClient.start();
    }
}

上述代码展示了如何使用 Java Socket 进行基本的 TCP 通信,包括数据的发送、接收及刷新缓存区。

目录

  1. Java TCP 网络编程:从可靠传输到 Socket 实战
  2. TCP 与 UDP 的区别与相同点
  3. 连接机制
  4. ServerSocket 与 Socket API 说明
  5. TCP 服务端实战代码演示
  6. 资源管理说明
  7. TCP 客户端实战代码演示
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • OpenClaw 生态 16 款 AI Agent 选型指南
  • Python 核心数据结构:集合与冻结集合详解
  • AI 提示词零基础入门与核心概念
  • 开源墙绘机:双轴张力控制低成本绘图系统
  • Windows 11 环境下 Python 3.12.5 安装与配置指南
  • Python 异常处理:try...except 语句详解
  • 基于 Bright Data 与 Haystack 实现股票新闻实时抓取与自动化总结
  • 2026 年国家自然科学基金 AI 使用声明撰写位置指南
  • WorkBuddy 配置 QQ 机器人指南
  • Seedance 2.0 重构 AIGC 工作流:语义理解与映射热更新实践
  • 手写 C++ TCP 服务器:自定义协议与粘包处理实战
  • Linux 文件 I/O 本质与内核视角:从 fopen 到 open
  • LangChain 进阶:Vector Stores 向量存储详解
  • GitHub 2021 年度报告:全球开发者达 7300 万,中国位居第二
  • 小米 MiMo-V2 系列发布:国产 AI 大模型新进展
  • Qwen3.5 与 OpenClaw 本地部署实战:30 分钟搭建 AI Agent
  • Figma Make 实测:AI 辅助前端代码生成的可行性分析
  • LLaMA-Factory 中微调算法的原理与显存优化思路
  • Qwen3-ForcedAligner-0.6B 部署与多浏览器兼容性实测
  • Linux 常用命令大全:系统管理与安全运维

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online