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内嵌Tomcat安全漏洞修复方式

    springboot内嵌Tomcat安全漏洞修复方式

    针对CVE-2020-1938漏洞,建议升级Tomcat至安全版本以避免受影响,影响版本包括:Apache Tomcat 9.x小于9.0.31、Apache Tomcat 8.x小于8.5.51、Apache Tomcat 7.x小于7.0.100及Apache Tomcat 6.x,
    2024-10-10
  • Spring中BeanFactory和ApplicationContext的作用和区别(推荐)

    Spring中BeanFactory和ApplicationContext的作用和区别(推荐)

    这篇文章主要介绍了Spring中BeanFactory和ApplicationContext的作用和区别,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-09-09
  • Spring IOC容器基于XML外部属性文件的Bean管理

    Spring IOC容器基于XML外部属性文件的Bean管理

    这篇文章主要为大家介绍了Spring IOC容器Bean管理XML外部属性文件,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • HelloSpringMVC配置版实现步骤解析

    HelloSpringMVC配置版实现步骤解析

    这篇文章主要介绍了HelloSpringMVC配置版实现步骤解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09
  • Java轻松实现Excel转PDF的实战指南

    Java轻松实现Excel转PDF的实战指南

    这篇文章主要介绍了两种将Excel转换为PDF的方法,第一种使用Spire.XLS免费版,第二种方法(破解版)支持多页转换,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下
    2026-03-03
  • 使用VisualVM分析日志

    使用VisualVM分析日志

    文章强调程序员需掌握多种工具(如JMeter、ELK、Prometheus等)应对工作挑战,避免线上事故,重点介绍VisualVM作为Java故障排查工具,通过分析大对象和GC监控,提升代码质量与问题定位效率
    2025-07-07
  • MyBatis之动态SQL和缓存使用及说明

    MyBatis之动态SQL和缓存使用及说明

    这篇文章主要介绍了MyBatis之动态SQL和缓存使用及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2026-05-05
  • Struts2源码分析之ParametersInterceptor拦截器

    Struts2源码分析之ParametersInterceptor拦截器

    这篇文章主要介绍了Struts2源码分析之ParametersInterceptor拦截器,ParametersInterceptor拦截器其主要功能是把ActionContext中的请求参数设置到ValueStack中,,需要的朋友可以参考下
    2019-06-06
  • Java复制(拷贝)数组的五种方法汇总

    Java复制(拷贝)数组的五种方法汇总

    java基础在Java中我们经常需要复制一个数组,下面这篇文章主要给大家介绍了关于Java复制(拷贝)数组的五种方法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-03-03
  • 手把手教你如何在idea中搭建SpringBoot项目

    手把手教你如何在idea中搭建SpringBoot项目

    这篇文章主要介绍了如何搭建一个SpringBoot项目,包括环境准备、创建新项目、探索项目结构以及展望未来,通过详细的步骤和实用的技巧,帮助开发者快速上手SpringBoot开发,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2025-02-02

最新评论