java短连接、长连接的详细说明

 更新时间:2025年07月05日 11:29:02   作者:泽553180  
短连接一般只会在client/server间传递一次请求操作,对于频繁请求资源的客户端适合使用长连接,这篇文章主要介绍了java短连接、长连接的详细说明,需要的朋友可以参考下

前言

在网络通信中,短连接(Short Connection)是指客户端与服务器建立连接后,仅完成一次或几次数据交互就立即断开连接的通信方式。

以下是关于短链接的详细说明:

一、短链接的核心特点

连接短暂
数据传输完成后立即关闭连接(如 HTTP 请求响应后断开)。

单向请求
通常由客户端主动发起请求,服务器响应后结束(无服务器主动推送)。

轻量级
无需维护连接状态,资源占用低

二、短链接的常见问题与解决方案

  1. 连接建立开销

    • 问题:每次请求需重新进行 TCP 三次握手,影响高并发性能。
    • 解决方案
      • 使用 HTTP/2 协议复用连接(长链接优化)。
      • 对频繁请求的接口使用长链接。
  2. 数据完整性

    • 问题:短链接可能因网络问题导致数据截断。
    • 解决方案
      • 设计请求 / 响应协议时添加校验机制(如 MD5 签名)。
      • 对大数据分块传输并验证。

三、典型应用场景

  • 网页浏览:浏览器通过 HTTP 短链接请求网页资源。
  • 文件下载:通过 HTTP 短链接下载文件(如图片、视频)。
  • API 调用:客户端调用 RESTful API 获取数据(如电商商品信息)。
  • 登录认证:客户端发送登录请求,服务器返回结果后断开。

在网络通信中,长链接(Long Connection)是指客户端与服务器建立连接后,保持该连接处于打开状态,允许双方在较长时间内持续进行数据交互,而不是每次通信后立即断开连接。

以下是关于长链接的详细说明:

一、长链接的核心特点

连接持久化
连接建立后不会主动关闭,可多次发送 / 接收数据(如即时聊天、实时推送)。

节省资源
避免频繁创建和销毁连接的开销(短链接每次请求都需重新建立 TCP 三次握手)。

双向通信
支持服务器主动向客户端推送消息(如消息通知、实时数据更新)。

二、长链接的常见问题与解决方案

  1. 连接断开问题

    • 原因:网络波动、服务器重启、防火墙超时。
    • 解决方案
      • 实现心跳机制(客户端定期发送心跳包,服务器响应确认存活)。
      • 设置合理的超时重连策略。
  2. 资源消耗

    • 问题:大量长链接可能占用服务器内存和端口资源。
    • 解决方案
      • 使用线程池或 NIO(非阻塞 IO)优化服务器性能。
      • 对空闲连接设置超时关闭(如 30 分钟无活动则断开)。
  3. 粘包 / 拆包问题

    • 问题:TCP 是流式传输,可能导致多条消息混合或被截断。
    • 解决方案
      • 定义消息协议(如固定长度头部 + 消息体)。
      • 使用DataInputStream按字节读取并解析。

三、典型应用场景

  • 即时通讯:微信、QQ 的消息推送。
  • 实时监控:股票行情、物联网设备状态上报。
  • 在线协作:协同编辑文档(如 Google Docs)。
  • 游戏服务器:多人在线游戏的实时交互。

短连接和长连接的比较

 现在举一个长连接的代码示例:实现多用户之间的私聊

import java.io.*;
import java.net.*;
import java.util.*;
 
// 服务器类
public class ChatServer {
    private static final int PORT = 12345;
    private static Map<String, PrintWriter> clients = new HashMap<>();
 
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            System.out.println("Chat Server is running on port " + PORT);
            while (true) {
                new ClientHandler(serverSocket.accept()).start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    // 客户端处理类
    private static class ClientHandler extends Thread {
        private Socket socket;
        private PrintWriter out;
        private BufferedReader in;
        private String clientName;
 
        public ClientHandler(Socket socket) {
            this.socket = socket;
        }
 
        @Override
        public void run() {
            try {
                out = new PrintWriter(socket.getOutputStream(), true);
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 
                // 获取客户端名称
                clientName = in.readLine();
                clients.put(clientName, out);
                System.out.println(clientName + " has joined the chat.");
 
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    if (inputLine.startsWith("/msg")) {
                        String[] parts = inputLine.split(" ", 3);
                        if (parts.length == 3) {
                            String recipient = parts[1];
                            String message = parts[2];
                            sendPrivateMessage(clientName, recipient, message);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                    clients.remove(clientName);
                    System.out.println(clientName + " has left the chat.");
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
 
        // 发送私聊消息
        private void sendPrivateMessage(String sender, String recipient, String message) {
            PrintWriter recipientWriter = clients.get(recipient);
            if (recipientWriter != null) {
                recipientWriter.println(sender + " whispers: " + message);
            } else {
                out.println("User " + recipient + " not found.");
            }
        }
    }
} 
-----------------------------------------------------------------------------
import java.io.*;
import java.net.*;
import java.util.Scanner;
 
// 客户端类
public class ChatClient {
    private static final String SERVER_ADDRESS = "localhost";
    private static final int PORT = 12345;
 
    public static void main(String[] args) {
        try (Socket socket = new Socket(SERVER_ADDRESS, PORT);
             PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
             BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
             Scanner scanner = new Scanner(System.in)) {
 
            System.out.print("Enter your name: ");
            String name = scanner.nextLine();
            out.println(name);
 
            // 启动一个线程来接收服务器消息
            new Thread(() -> {
                try {
                    String inputLine;
                    while ((inputLine = in.readLine()) != null) {
                        System.out.println(inputLine);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
 
            // 读取用户输入并发送消息
            String input;
            while (scanner.hasNextLine()) {
                input = scanner.nextLine();
                out.println(input);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}       

代码中体现长连接的部分

服务器端(ChatServer)

  • 持续监听

    java

    try (ServerSocket serverSocket = new ServerSocket(PORT)) {
        System.out.println("Chat Server is running on port " + PORT);
        while (true) {
            new ClientHandler(serverSocket.accept()).start();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

  • 服务器通过 ServerSocket 监听指定端口,while (true) 循环会持续不断地接受新的客户端连接请求。一旦有新的客户端连接进来,就会为其创建一个 ClientHandler 线程进行处理,整个过程中服务器的监听状态是一直保持的。
  • 客户端处理线程(ClientHandler)

    java

    String inputLine;
    while ((inputLine = in.readLine()) != null) {
        if (inputLine.startsWith("/msg")) {
            String[] parts = inputLine.split(" ", 3);
            if (parts.length == 3) {
                String recipient = parts[1];
                String message = parts[2];
                sendPrivateMessage(clientName, recipient, message);
            }
        }
    }

    每个 ClientHandler 线程负责与一个客户端进行通信。while ((inputLine = in.readLine()) != null) 循环会持续读取客户端发送过来的消息,只要客户端没有主动断开连接,这个循环就会一直运行,从而保持与客户端的连接处于活跃状态。

客户端(ChatClient)

  • 持续接收消息

    java

    客户端启动一个单独的线程来持续接收服务器发送过来的消息。只要服务器没有主动断开连接,这个线程就会一直运行,不断地从输入流中读取数据,以此维持与服务器的连接。
  • 持续发送消息

    java

    String input;
    while (scanner.hasNextLine()) {
        input = scanner.nextLine();
        out.println(input);
    }

    客户端通过 while (scanner.hasNextLine()) 循环持续读取用户的输入,并将其发送给服务器。只要用户持续输入消息,客户端就会持续向服务器发送数据,连接也会一直保持。

综上所述,代码通过不断地在连接上进行数据的读写操作,保持了客户端和服务器之间的连接,属于长连接的实现方式。

总结

到此这篇关于java短连接、长连接详细说明的文章就介绍到这了,更多相关java短连接、长连接内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot的war和jar包的使用详解

    springboot的war和jar包的使用详解

    这篇文章主要介绍了springboot的war和jar包的使用详解,非常不错,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2018-11-11
  • SpringBoot使用redis生成订单号的实现示例

    SpringBoot使用redis生成订单号的实现示例

    在电商系统中,生成唯一订单号是常见需求,本文介绍如何利用SpringBoot和Redis实现订单号的生成,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-09-09
  • java检测redis是否可用的方法示例

    java检测redis是否可用的方法示例

    这篇文章主要给大家介绍了关于java检测redis是否可用的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • SpringBoot如何整合nacos详解

    SpringBoot如何整合nacos详解

    今天教各位小伙伴SpringBoot是如何整合nacos的,文中有非常详细的代码示例,对正在学习Java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-06-06
  • 详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别

    这篇文章主要介绍了详解java CountDownLatch和CyclicBarrier在内部实现和场景上的区别,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • springboot中poi使用操作方法

    springboot中poi使用操作方法

    在项目中,有很多对excel的操作,大都数时候我们都会使用poi工具类,本文将介绍poi的一些使用方法,感兴趣的朋友跟随小编一起看看吧
    2023-08-08
  • Java8之lambda表达式基本语法

    Java8之lambda表达式基本语法

    本文通过示例大家给大家介绍了java8之lambda表达式的基本语法,感兴趣的的朋友一起看看吧
    2017-08-08
  • Maven+SSM框架实现简单的增删改查

    Maven+SSM框架实现简单的增删改查

    这篇文章主要介绍了Maven+SSM框架实现简单的增删改查,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • 详解jenkins自动部署springboot应用的方法

    详解jenkins自动部署springboot应用的方法

    这篇文章主要介绍了详解jenkins自动部署springboot应用的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-08-08
  • 深入理解java异常处理机制及应用

    深入理解java异常处理机制及应用

    本篇文章主要介绍了java异常处理机制及应用,异常处理机制是Java语言的一大特色。从异常处理的机制、异常处理的方法、异常处理的原则等方面介绍Java语言的异常处理技术,有兴趣的可以了解一下。
    2016-12-12

最新评论