Java网络编程入门:从基础原理到实践(二)

目录

1. 网络编程基础:搞懂设备通信的底层逻辑

1.1 为啥需要网络编程?—— 让设备 “互通有无”

1.2 什么是网络编程?—— 给数据 “定规矩、找路线”

1.3 网络编程的基本概念:理清通信里的角色和流程

1.3.1 发送端和接收端 —— 数据的 “发信人” 和 “收信人”

1.3.2 请求和响应 —— 通信的 “一问一答” 

1.3.3 客户端和服务端 —— 稳定的 “需求方” 和 “服务方” 

1.3.4 常见的客户端服务端模型

2. Socket 套接字:网络通信的 “连接器” 

2.1 概念:网络通信的 “电话”

2.2 分类:两种通信 “风格

2.2.1 数据报套接字

2.2.2 流套接字

2.3 Java数据报套接字通信模型

2.4 Java流套接字通信模型

2.5 Socket 编程注意事项:避坑要点 

3. UDP 数据报套接字编程:简单高效的 “快传” 实践 

3.1 API 介绍:核心工具

3.1.1 DatagramSocket

3.1.2 DatagramPacket 

3.1.3 InetSocketAddress

3.2 代码示例:UDP 通信全流程 

3.2.1 UDP Echo Server

3.2.2 UDP Echo Client

3.2.3 3. UDP Dict Serve 字典服务器

4. TCP 流套接字编程:可靠传输的 “保障”

4.1 API 介绍:构建可靠连接

4.1.1 ServerSocket

4.1.2 Socket

​编辑4.2 代码示例:TCP 通信实践

4.2.1 TCP Echo Server

4.2.2 TCP Echo Client

5. 长短连接:按需选择通信模式

5.1 短连接与长连接的定义

5.2 短连接与长连接的核心区别

5.2.1 连接建立与关闭的耗时差异

5.2.2 主动请求的发起方差异

5.2.3 适用场景差异

5.3 长连接的 “扩展痛点” 与优化方向

5.3.1 BIO 长连接的资源瓶颈

5.3.2 NIO 优化长连接的思路

5.4 总结:按需选型,平衡效率与资源


        网络编程听着高深,其实就是解决 “设备之间咋传数据” 的问题。想象一下,你手机刷短视频,本质是手机(客户端)和短视频服务器(服务端)在传数据;玩联机游戏,是你电脑和游戏服务器、队友设备在传数据。这篇就把网络编程最基础的逻辑和核心工具 Socket,掰开揉碎了讲,保证像唠家常一样好懂 。

1. 网络编程基础:搞懂设备通信的底层逻辑

1.1 为啥需要网络编程?—— 让设备 “互通有无”

        用手机点外卖,手机得把 “我要点宫保鸡丁” 的需求发给外卖平台服务器;玩联机游戏,你操控角色的动作得传给队友的设备;智能手表测的心率数据,得传到手机 App 上显示……网络编程就是让这些 “需求、动作、数据”,能在不同设备(或同一设备的不同程序)之间准确、高效传递的技术

简单说:没有网络编程,所有跨设备的功能全废!手机只能当计算器,电脑连不上网页,智能设备数据也传不出去,所有的网络资源都无法访问,世界直接 “断网瘫痪” 。

  • 所谓的网络资源,其实就是在网络中可以获取的各种数据资源。
  • 而所有的网络资源,都是通过网络编程来进行数据传输的。

1.2 什么是网络编程?—— 给数据 “定规矩、找路线”

        网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。

        当然,我们只要满足进程不同就行;所以即便是同一个主机,只要是不同进程,基于网络来传输数据,也属于网络编程。 

        特殊的,对于开发来说,在条件有限的情况下,一般也都是在一个主机中运行多个进程来完成网络编程。

        但是,我们一定要明确,我们的目的是提供网络上不同主机,基于网络来传输数据资源:

  • 进程A:编程来获取网络资源
  • 进程B:编程来提供网络资源

        网络编程的核心,就是控制程序按照 “网络协议”(比如 TCP、UDP),把数据打包、发送、接收、解析。举个例子:你用微信发消息 “吃了吗”,手机里的微信程序会:

  1. 打包:把文字转成符合网络协议的 “数据包”(类似把信装进信封,写上收件人地址);
  2. 发送:通过网络(WiFi、基站)把数据包传输出去(类似快递小哥把信运到目的地);
  3. 接收:对方的微信程序收到数据包(类似收件人拿到信);
  4. 解析:把数据包还原成 “吃了吗” 的文字(类似拆信封读内容)。

        整个过程,就是网络编程在 “暗中操作”,让数据能跨设备 “跑来跑去”。

1.3 网络编程的基本概念:理清通信里的角色和流程

        这些概念看着抽象,对应生活场景就秒懂了,一个个看:

1.3.1 发送端和接收端 —— 数据的 “发信人” 和 “收信人”

  • 发送端:数据的发送方进程,称为发送端,它是主动发数据的一方。比如你给朋友发微信,你手机就是发送端;游戏里你开枪,你的设备就是发送端(把 “开枪动作” 发出去)。发送端主机即网络通信的源主机。
  • 接收端:数据的接收方进程,称为接收端,它是被动收数据的一方。朋友的手机收你的微信、队友的设备收你 “开枪动作”,它们就是接收端。接收端主机即网络通信中的目的主机。
  • 收发端:发送端和接收端两端,也简称为收发端

注意:发送端和接收端只是相对的,角色会切换!只是一次网络数据传输产生数据流向后的概念。比如你和朋友互相发消息,你们的手机会轮流当 “发送端” 和 “接收端”,像打乒乓球一样来回传数据。

1.3.2 请求和响应 —— 通信的 “一问一答” 

        一般来说,获取一个网络资源,涉及到两次网络数据传输:

                •  第一次:请求数据的发送。

                •  第二次:响应数据的发送。

请求(Request):发送端主动提的 “需求”。比如你打开抖音,抖音 App 会给服务器发 “请求”:“给我推荐点搞笑视频”;你登录微信,微信 App 会发 “请求”:“验证这个账号密码对不对”。

响应(Response):接收端针对请求的 “回复”。服务器收到抖音的请求,回复 “这是搞笑视频列表”;收到微信登录请求,回复 “密码正确,登录成功”(或 “密码错误,失败” )

生活 analogy:你去餐厅(客户端)喊 “来份牛肉面”(请求),服务员(服务端)回复 “好的,马上做”(响应),就是典型的 “请求 - 响应”。

1.3.3 客户端和服务端 —— 稳定的 “需求方” 和 “服务方” 

  • 客户端(Client):主动找别人获取服务的程序 / 设备。手机 App(抖音、微信)、电脑上的浏览器(Chrome、Edge)、智能手表的 App,都是客户端。特点是 “按需连接”:需要服务时才主动连服务器,不用服务时就 “躺平”。
  • 服务端(Server):长期在线、专门给别人提供服务的程序 / 设备。抖音的后台服务器、微信的认证服务器、游戏的对战服务器,都是服务端。特点是 “7×24 小时待命”:不管有没有客户端找它,它都开着提供服务,随时准备响应请求。

再举个生活例子:你用美团 App(客户端)点外卖,美团的服务器(服务端)负责接收订单、分配骑手,就是 “客户端 - 服务端” 的典型交互。

1.3.4 常见的客户端服务端模型

最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:

  1. 客户端先发送请求到服务端
  2. 服务端根据请求数据,执行相应的业务处理
  3. 服务端返回响应:发送业务处理结果
  4. 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

  • C/S 模型(客户端 / 服务端 ):需安装专门客户端软件(如微信 App )。优点是功能定制强,能利用本地资源;缺点是客户端需手动更新 。
  • B/S 模型(浏览器 / 服务端 ):通过浏览器访问(如知乎网页版 )。优点是使用方便、跨设备易访问;缺点是受浏览器功能限制,复杂交互体验弱于 C/S 。

2. Socket 套接字:网络通信的 “连接器” 

2.1 概念:网络通信的 “电话”

        Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元,是程序实现网络通信的基础载体。基于Socket套接字的网络程序开发就是网络编程。把它想象成 “网络电话”。程序通过 Socket 建立与其他设备的连接,在连接上发送和接收数据,就像通过电话线路实现双方通话。无论是 UDP 还是 TCP 通信,都得依靠 Socket 搭建数据传输的通道 。

2.2 分类:两种通信 “风格

2.2.1 数据报套接字

        使用传输层UDP协议,UDP,即User Datagram Protocol(用户数据报协议),传输层协议。类似 “发短信”,发送端把数据打包成 “数据报” 直接发,不管接收端状态。

优点:传输速度快,无需建立连接开销;

缺点:可能丢数据、数据无序。适合实时性要求高、容忍少量丢包的场景(如在线视频直播、游戏实时位置同步 )

  • 无连接
  • 不可靠传输
  • 面向数据报
  • 有接收缓冲区,无发送缓冲区
  • 大小受限:一次最多传输64k

        对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如100个字节,必须一次发送,接收也必须一次接收100个字节,而不能分100次,每次接收1个字节。

2.2.2 流套接字

        使用传输层TCP协议,TCP,即Transmission Control Protocol(传输控制协议),传输层协议。如同 “打电话”,通信前需三次握手建立连接,保证数据可靠、有序传输,传输完四次挥手断开连接

优点:数据传输可靠;

缺点:建立 / 断开连接有额外耗时,速度稍慢。适合文件传输(需完整数据 )、登录验证(关键数据不能丢 )等场景 。

  • 有连接
  • 可靠传输
  • 面向字节流
  • 有接收缓冲区,也有发送缓冲区
  • 大小不限

        对于字节流来说,可以简单的理解为,传输数据是基于IO流,流式数据的特征就是在IO流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。

2.3 Java数据报套接字通信模型

        对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报。

        java中使用UDP协议通信。主要基于 DatagramSocket(收发器 )和 DatagramPacket(数据报载体 )实现。发送时,把数据转字节数组,构建 DatagramPacket 并指定目标地址 / 端口,通过 DatagramSocket 发送;接收时,创建空 DatagramPacket 当缓冲区,用 DatagramSocket 接收,再解析数据 。对于一次发送及接收UDP数据报的流程如下:

        以上只是一次发送端的UDP数据报发送,及接收端的数据报接收,并没有返回的数据。也就是只有请求,没有响应。对于一个服务端来说,重要的是提供多个客户端的请求处理及响应,流程如下: 

2.4 Java流套接字通信模型

        java中使用TCP通信协议,主要依赖 ServerSocket(服务端 “大门”,监听客户端连接 )和 Socket(客户端 / 服务端连接后的数据通道 )。服务端用 ServerSocket 绑定端口监听,如 ServerSocket serverSocket = new ServerSocket(9999); ;客户端用 Socket 连服务端,如 Socket clientSocket = new Socket("127.0.0.1", 9999); 。连接建立后,通过 Socket 的输入输出流(像水管 )收发数据,保证数据有序、可靠传输 。

2.5 Socket 编程注意事项:避坑要点 

在 Socket 编程开发中,这些关键问题得留意,避免踩坑:

  1. 客户端与服务端部署场景
    开发调试时,常在同一主机开两个进程模拟客户端、服务端,但真实环境里,客户端和服务端一般分属不同主机 。开发要考虑跨主机通信的网络差异(如防火墙、网段限制),别只依赖本地调试逻辑。

  2. 目标标识:IP + 端口
    数据传输得明确 “终点”,目的 IP 定位目标主机,目的端口号 定位主机内接收数据的进程。编程时要准确设置这两个参数,否则数据发错地方,通信直接失败。

  3. 套接字类型与协议层
    Socket 编程用 流套接字(基于 TCP) 或 数据报套接字(基于 UDP) 开发,对应传输层 TCP/UDP 协议。但光有传输层还不够,应用层协议得自己设计(比如定义数据包格式、指令含义),这部分后续会详细讲怎么规划。

  4. 端口占用冲突问题                                                                                                                  如果一个进程A已经绑定了一个端口,再启动一个进程B绑定该端口,就会报错,这种情况也叫端口被占用。对于java进程来说,端口被占用的常见报错信息如下: 此时需要检查进程B绑定的是哪个端口,再查看该端口被哪个进程占用。

解决端口被占用的问题:

  • 如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B
  • 如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。

3. UDP 数据报套接字编程:简单高效的 “快传” 实践 

3.1 API 介绍:核心工具

3.1.1 DatagramSocket

        UDP 通信的 “收发器”,用于发送和接收UDP数据报。服务端常绑定固定端口(如 DatagramSocket serverSocket = new DatagramSocket(8888); ),方便客户端定位;客户端一般不绑定固定端口(DatagramSocket clientSocket = new DatagramSocket(); ),由系统分配 。

构造方法:

常用方法: 

3.1.2 DatagramPacket 

        “数据报载体”,包含数据、目标地址(发送时 )或源地址(接收时 )。发送时,构建 DatagramPacket 需指定数据字节数组、目标地址 / 端口;接收时,创建空 DatagramPacket 当缓冲区,用 DatagramSocket 接收后解析数据 。

构造方法:

常用方法: 

        构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress
来创建。 

3.1.3 InetSocketAddress

        InetSocketAddress 是 SocketAddress 的子类。

构造方法:

3.2 代码示例:UDP 通信全流程 

3.2.1 UDP Echo Server

public class UdpEchoServer {// 用于网络通信的套接字对象,就像服务器的"通信接口"private DatagramSocket socket = null;// 服务器构造方法,需要指定一个端口号来启动服务// 端口号就像快递柜的编号,方便客户端找到对应的服务public UdpEchoServer(int port) throws SocketException {// 绑定指定端口,启动服务器的通信接口socket = new DatagramSocket(port);}// 服务器的启动方法,一旦调用就开始工作public void start() throws IOException {System.out.println("服务器启动成功!正在等待客户端连接...");// 服务器需要一直运行,用死循环来保持工作状态while (true) {// 每次循环处理一个客户端的请求和响应// 1. 创建一个数据包对象,用来接收客户端发来的数据// 就像准备一个"收件盒",指定最大能装4096字节的数据DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);// 等待接收客户端的数据,这一步会"卡住"直到有数据到来socket.receive(requestPacket);// 把接收到的字节数据转换成字符串,方便处理// 注意:只转换实际收到的长度,避免多余的空字符String request = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2. 处理请求,得到响应结果// 对于回显服务器来说,直接把收到的内容返回即可String response = process(request);// 3. 把响应结果发回给客户端// 准备一个"发件盒",装着要发送的内容,以及客户端的地址和端口DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),  // 要发送的内容(转换为字节数组)response.getBytes().length,  // 内容的长度requestPacket.getSocketAddress()  // 客户端的地址和端口(从请求中获取));// 发送响应数据socket.send(responsePacket);// 打印日志,记录通信详情System.out.printf("[客户端 %s:%d] 收到: %s, 回复: %s\n",requestPacket.getAddress().toString(),  // 客户端IP地址requestPacket.getPort(),  // 客户端端口request,  // 客户端发送的内容response  // 服务器回复的内容);}}// 处理请求的方法// 这里实现的是回显功能:输入什么,就返回什么public String process(String request) {return request;}// 程序入口:启动服务器public static void main(String[] args) throws IOException {// 创建服务器实例,指定端口号9090UdpEchoServer server = new UdpEchoServer(9090);// 启动服务器server.start();}
}

3.2.2 UDP Echo Client

public class UdpEchoClient {// 客户端的通信接口,就像打电话用的"手机"private DatagramSocket socket = null;// 服务器的IP地址,类似对方的"电话号码"private String serverIp;// 服务器的端口号,类似对方"手机上的某个APP"private int serverPort;// 客户端构造方法:需要知道服务器的IP和端口才能连接// IP地址格式是"点分十进制",比如"192.168.1.1"public UdpEchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;// 初始化客户端的通信接口(不用指定端口,系统会自动分配一个)socket = new DatagramSocket();}// 客户端启动方法:开始和服务器通信public void start() throws IOException {System.out.println("客户端启动成功!可以开始发送消息了...");// 创建Scanner对象,用于读取用户在控制台输入的内容Scanner scanner = new Scanner(System.in);// 循环处理:不断读取用户输入并和服务器交互while (true) {// 显示提示符号,告诉用户可以输入内容了System.out.print("-> ");// 检查用户是否还有输入(如果输入结束就退出循环)if (!scanner.hasNext()) {break;}// 读取用户输入的内容(这就是要发给服务器的请求)String request = scanner.next();// 构造要发送的数据包:相当于把消息装进"信封"DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),  // 要发送的内容(转成字节数组)request.getBytes().length,  // 内容的长度InetAddress.getByName(serverIp),  // 服务器的IP地址(把字符串转成网络地址)serverPort  // 服务器的端口号);// 发送数据包:相当于把信封"寄出去"socket.send(requestPacket);// 准备接收服务器的回复:创建一个"收件盒"DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);// 等待接收服务器的回复:这一步会"卡住"直到收到消息socket.receive(responsePacket);// 把服务器回复的字节数据转成字符串String response = new String(responsePacket.getData(), 0, responsePacket.getLength());// 在控制台显示服务器的回复内容System.out.println(response);}}// 程序入口:启动客户端public static void main(String[] args) throws IOException {// 创建客户端实例,连接到本机(127.0.0.1)的9090端口服务器UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);// 启动客户端client.start();}
}

3.2.3 3. UDP Dict Serve 字典服务器

思路:客户端发单词,服务器查字典(用 Map 存单词 - 翻译 )返回翻译。只需要重写 process。比如初始化 Map<String, String> dict = new HashMap<>(); ,存入 dict.put("apple", "苹果"); 等。服务器接收单词后,在 dict 中查找,把翻译当响应发回;客户端发请求、收翻译并展示。通过这个示例,能更灵活理解 UDP 套接字的应用 。

4. TCP 流套接字编程:可靠传输的 “保障”

4.1 API 介绍:构建可靠连接

4.1.1 ServerSocket

        ServerSocket 是创建TCP服务端Socket的API。是服务端 “大门”,监听客户端连接。创建时绑定端口,如ServerSocket serverSocket = new ServerSocket(9090);然后通过 serverSocket.accept() 阻塞等客户端连接,有连接时返回 Socket 用于通信 。

构造方法:

其它方法: 

4.1.2 Socket

        Socket 是客户端发起连接或服务端通过 ServerSocket.accept () 响应连接后得到的通信端点,双方建立连接后,用其保存的对端信息收发数据,客户端创建时需指定服务端 IP 和端口 ,服务端通过该 Socket 的输入输出流交互 。

构造方法:

其它方法:

4.2 代码示例:TCP 通信实践

4.2.1 TCP Echo Server

public class TcpEchoServer {// 服务器的"总机",负责接听客户端的连接请求ServerSocket serverSocket = null;// 构造方法:创建服务器并指定端口号(就像给总机分配一个电话号码)public TcpEchoServer(int port) throws IOException {serverSocket = new ServerSocket(port);}// 启动服务器的方法public void start() throws IOException {System.out.println("服务器启动成功!等待客户端连接...");// 创建一个线程池,用来处理多个客户端的请求(相当于多个接线员)// newCachedThreadPool表示可以根据需要自动创建新线程ExecutorService pool = Executors.newCachedThreadPool();// 服务器一直运行,不断接收新的客户端连接while (true) {// 等待客户端连接(总机接听电话)// 这一步会"卡住",直到有客户端来连接Socket clientSocket = serverSocket.accept();// 收到连接后,交给线程池处理(安排一个接线员专门服务这个客户端)pool.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}}// 处理单个客户端连接的方法(接线员和客户的通话过程)private void processConnection(Socket clientSocket) {// 打印客户端上线信息:包含客户端的IP和端口System.out.printf("[%s:%d] 客户端上线啦\n", clientSocket.getInetAddress(), clientSocket.getPort());// try-with-resources语法:自动关闭资源,不用手动写close()try (// 获取输入流:用来读取客户端发送的消息(相当于听客户说话)InputStream inputStream = clientSocket.getInputStream();// 获取输出流:用来向客户端发送消息(相当于跟客户说话)OutputStream outputStream = clientSocket.getOutputStream()) {// 创建Scanner对象,方便读取输入流中的文本Scanner scanner = new Scanner(inputStream);// 循环处理客户端的请求while (true) {// 判断客户端是否还有数据发送(如果没有,说明客户端要下线了)if (!scanner.hasNext()) {System.out.printf("[%s:%d] 客户端下线啦\n", clientSocket.getInetAddress(), clientSocket.getPort());break;}// 1. 读取客户端发送的请求内容String request = scanner.next();// 2. 处理请求(回显服务器直接返回相同内容)String response = process(request);// 3. 把响应写回给客户端// 创建PrintWriter方便写入文本PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(response);// 刷新缓冲区:确保数据立刻发送出去(不然可能留在缓存里)printWriter.flush();// 打印日志:记录这次通信的详情System.out.printf("[%s:%d] 收到: %s, 回复: %s\n",clientSocket.getInetAddress(),clientSocket.getPort(),request,response);}} catch (IOException e) {// 捕获并打印异常信息(比如网络中断等问题)e.printStackTrace();}}// 处理请求的核心方法(回显逻辑:输入什么返回什么)private String process(String request) {return request;}// 程序入口:启动服务器public static void main(String[] args) throws IOException {// 创建服务器实例,绑定9090端口TcpEchoServer server = new TcpEchoServer(9090);// 启动服务器server.start();}
}

4.2.2 TCP Echo Client

public class TcpEchoClient {// 客户端的"电话",用来和服务器建立连接并通话private Socket clientSocket = null;// 构造方法:初始化客户端,需要知道服务器的IP和端口(相当于知道对方的电话号码)public TcpEchoClient(String serverIp, int serverPort) throws IOException {// 连接服务器:就像拨打指定的电话号码clientSocket = new Socket(serverIp, serverPort);}// 启动客户端:开始和服务器通信public void start() {System.out.println("客户端启动成功!可以开始聊天啦...");// try-with-resources语法:自动关闭输入输出流,不用手动关闭try (// 输入流:用来接收服务器发过来的消息(相当于耳朵,听服务器说话)InputStream inputStream = clientSocket.getInputStream();// 输出流:用来向服务器发送消息(相当于嘴巴,跟服务器说话)OutputStream outputStream = clientSocket.getOutputStream()) {// 扫描器1:用来读取用户在控制台输入的内容(从键盘读)Scanner scannerConsole = new Scanner(System.in);// 扫描器2:用来读取服务器发送过来的消息(从网络读)Scanner scannerNetwork = new Scanner(inputStream);// 打印器:用来向服务器发送消息(包装输出流,方便写文本)PrintWriter writer = new PrintWriter(outputStream);// 循环聊天:不断读取用户输入并发送给服务器,再接收服务器回复while (true) {// 显示提示符号,告诉用户可以输入内容了System.out.printf("-> ");// 检查用户是否还有输入(如果没有输入,就退出循环)if (!scannerConsole.hasNext()) {break;}// 1. 读取用户在控制台输入的内容(要发给服务器的消息)String request = scannerConsole.next();// 2. 把消息发送给服务器writer.println(request);// 刷新缓冲区:确保消息立刻发出去(不然可能存在缓存里没发送)writer.flush();// 3. 等待并读取服务器的回复String response = scannerNetwork.next();// 4. 在控制台显示服务器的回复内容System.out.println(response);}} catch (IOException e) {// 捕获并打印异常(比如网络断开等问题)e.printStackTrace();} finally {// 最后一定要关闭客户端的"电话",释放资源try {clientSocket.close();} catch (IOException e) {e.printStackTrace();}}}// 程序入口:启动客户端public static void main(String[] args) throws IOException {// 创建客户端实例,连接到本机(127.0.0.1)的9090端口服务器TcpEchoClient client = new TcpEchoClient("127.0.0.1", 9090);// 启动客户端,开始通信client.start();}
}

5. 长短连接:按需选择通信模式

        在 TCP 通信体系里,连接的建立与关闭时机,直接界定了短连接和长连接两种模式。合理选用,能让程序在效率、资源占用间找到平衡,适配不同业务场景。

5.1 短连接与长连接的定义

TCP 传输数据依赖先建立连接,“何时关闭连接” 是区分短、长连接的核心

  • 短连接:每次完成 “接收数据 + 返回响应” 后,立即关闭连接 。如同 “一锤子买卖”,一次连接仅支撑单次收发数据,下次交互需重新建连。
  • 长连接:保持连接状态不关闭,允许双方持续收发数据 。像 “持续对话”,一次建连可支撑多次数据交互,直至主动断开或网络异常。

5.2 短连接与长连接的核心区别

对比短、长连接,从建连开销到适用场景,差异显著:

5.2.1 连接建立与关闭的耗时差异

  • 短连接:每次请求 - 响应,都要经历 “建连→传数据→关连” 全流程 。频繁交互时,建连、关连的耗时会叠加,拖慢整体效率。
  • 长连接:仅首次需完整建连,后续请求 - 响应直接复用已连通道 。省掉重复建连、关连的耗时,高频交互场景下效率优势明显。

5.2.2 主动请求的发起方差异

  • 短连接:通常由客户端主动发起请求,服务端被动响应 。典型如浏览器访问静态网页,客户端发请求,服务端回数据后关连,服务端很少主动 “推送”。
  • 长连接:支持双向主动通信 。既允许客户端主动发请求(如聊天时发消息 ),也支持服务端主动推送数据(如即时通讯的新消息通知、实时行情更新 )。

5.2.3 适用场景差异

  • 短连接:适配客户端请求频率低的场景 。如浏览新闻网页(单次请求即可获取内容 )、查询静态数据接口(查天气、物流信息 ),无需持续保持连接,“即用即关” 省资源。
  • 长连接:专为客户端与服务端高频通信设计 。像聊天室(持续收发消息 )、实时游戏(同步玩家操作、状态 )、金融行情推送(秒级更新数据 ),依赖长连接实现低延迟、高实时性交互。

5.3 长连接的 “扩展痛点” 与优化方向

        长连接虽高效,但若基于传统 BIO(同步阻塞 IO )实现,会面临系统资源占用过高问题:

5.3.1 BIO 长连接的资源瓶颈

        BIO 模式下,每个长连接对应一个阻塞线程 。连接需持续 “阻塞等待” 数据,若有 1 万长连接,服务端需创建 1 万线程,内存、线程切换开销会直接 “压垮” 系统。

5.3.2 NIO 优化长连接的思路

        为解决 BIO 缺陷,Java 引入 NIO(同步非阻塞 IO ) ,通过 Selector(多路复用器 ) 实现:

  • 少量线程管理大量连接,线程无需阻塞等待,而是由 Selector 监听 “哪些连接有数据可读 / 可写”,按需处理。
  • 极大降低资源消耗,支撑高并发长连接场景(如百万级在线的即时通讯系统 ),主流框架(Netty )也基于 NIO 封装,简化长连接开发。

5.4 总结:按需选型,平衡效率与资源

        短连接 “简单轻量”,适合低频交互;长连接 “高效持久”,适配高频、实时场景 。实际开发中,需结合业务需求:

  • 若做新闻网站、静态数据接口,选短连接省心省力;
  • 若开发聊天、实时游戏,长连接是必选项,且建议基于 NIO/Netty 优化资源占用。
    理解长短连接的本质差异,才能让网络通信既高效又稳定,贴合业务需求 。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/915934.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/915934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

XSS内容分享

反射型XSS &#xff1a;反射型XSS 是非持久性、参数型的跨站脚本。反射型XSS 的JS 代码在Web 应用的参数&#xff08;变量&#xff09;中&#xff0c;如搜索框的反射型XSS。在搜索框中&#xff0c;提交PoC[scriptalert(/xss/)/script]&#xff0c;点击搜索&#xff0c;即可触发…

电线杆距离居民区的安全距离【重要!!!】

10kV架空电线安全距离购房指南 中国大陆地区10kV架空电线距居民住宅需要满足1.5米水平安全距离&#xff08;裸导线&#xff09;和6.5米垂直安全距离的国家强制标准。根据现行法规&#xff0c;10kV系统的电磁辐射水平极低&#xff0c;对居民健康影响可忽略不计&#xff0c;但购房…

河南萌新联赛2025第(二)场:河南农业大学

我看到花儿在绽放 我听到鸟儿在歌唱 我看到人们匆匆忙忙 我看到云朵在天上 我听到小河在流淌 我看到人们漫步在路上 河南萌新联赛2025第&#xff08;二&#xff09;场&#xff1a;河南农业大学 河南萌新联赛2025第&#xff08;二&#xff09;场&#xff1a;河南农业大学_ACM/N…

unixbench系统性能测试

unixbench系统性能测试 环境&#xff1a; UnixBench: 6.0.0(2025-05-21)简介 UnixBench 是一款经典的 Unix/Linux 系统性能测试工具&#xff0c;主要用于评估系统的CPU 运算能力、内存性能、多线程处理能力以及部分系统调用&#xff08;如进程创建、文件操作&#xff09;的效率…

上线了,自己开发的刷题小程序,vue3.0

嘿&#xff0c;最近我搞了个Java刷题的小程序&#xff0c;用Vue写的&#xff0c;界面和功能都还挺完整的。今天就来跟大家聊聊这个小程序是怎么实现的&#xff0c;代码里都藏着哪些小细节。 先看整体结构&#xff0c;我把整个页面分成了几个大块&#xff1a;顶部导航栏、题目内…

嵌入式开发学习———Linux环境下数据结构学习(三)

单向循环链表单向循环链表是一种特殊的单向链表&#xff0c;尾节点的指针指向头节点&#xff0c;形成一个闭环。适用于需要循环访问的场景&#xff0c;如轮询调度。结构特点&#xff1a;每个节点包含数据域和指向下一个节点的指针&#xff0c;尾节点的指针指向头节点而非空值。…

【华为机试】684. 冗余连接

文章目录684. 冗余连接描述示例 1示例 2提示解题思路核心分析问题转化算法选择策略1. 并查集 (Union-Find) - 推荐2. 深度优先搜索 (DFS)3. 拓扑排序算法实现详解方法一&#xff1a;并查集 (Union-Find)方法二&#xff1a;深度优先搜索 (DFS)数学证明并查集算法正确性证明时间复…

Ⅹ—6.计算机二级综合题7---10套

目录 第7套 【填空题】 【修改题】 【设计题】 第8套 【填空题】 【修改题】 【设计题】 第9套 【填空题】 【修改题】 【设计题】 第10套 【填空题】 【修改题】 【设计题】 第7套 【填空题】 题目要求:给定程序中,函数fun的功能是:将形参s所指字符串中所…

【三桥君】大语言模型计算成本高,MoE如何有效降低成本?

​ 你好&#xff0c;我是 ✨三桥君✨ &#x1f4cc;本文介绍&#x1f4cc; >> 一、引言 在AI技术飞速发展的当下&#xff0c;大语言模型&#xff08;LLM&#xff09;的参数规模不断增长&#xff0c;但随之而来的计算成本问题也日益凸显。如何在保持高效推理能力的同时扩…

Python游戏开发利器:Pygame从入门到实战全解析

引言 Pygame是Python中最受欢迎的2D游戏开发库之一&#xff0c;基于SDL&#xff08;Simple DirectMedia Layer&#xff09;构建&#xff0c;支持图形渲染、音效处理、事件响应等核心功能。无论是开发简单的休闲游戏&#xff0c;还是复杂的交互式应用&#xff0c;Pygame都能提供…

行为型模式-协作与交互机制

行为型模式聚焦于对象间的行为交互&#xff0c;通过规范对象协作方式提升系统的灵活性与可扩展性。在分布式系统中&#xff0c;由于多节点异步通信、网络不可靠性及状态一致性挑战&#xff0c;行为型模式需针对分布式特性进行适应性设计。本文从观察者、策略、命令、责任链、状…

spring boot 整合 Spring Cloud、Kafka 和 MyBatis菜鸟教程

环境准备确保项目中已引入 Spring Boot、Spring Cloud、Kafka 和 MyBatis 的依赖。以下是一个典型的 Maven 依赖配置&#xff1a;<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artif…

20 BTLO 蓝队靶场 Sticky Situation 解题记录

难度&#xff1a;5/10考察技能: Windows admin, Autopsy 使用场景&#xff1a;分析USB设备使用情况Autopsy使用注意&#xff1a;用管理员打开&#xff0c;在实际分析时注意先复制一个镜像文件&#xff0c;保存好原文件常用的Windows USB 取证的位置:Windows XP:Registry Key: U…

安装及配置Go语言开发环境与VSCode集成指南

安装Go语言开发 安装Go语言开发环境是第一步。访问Go官网&#xff0c;下载适合操作系统的安装包&#xff0c;如果进不去可以访问Go官方镜像站。 根据自己的系统选择对应的安装包&#xff0c;我这边是Windows系统就点击安装第一个即可。 点击下一步即可。 验证安装是否成功可以…

专题:2025微短剧行业生态构建与跨界融合研究报告|附100+份报告PDF汇总下载

原文链接&#xff1a; https://tecdat.cn/?p43384 分析师&#xff1a;Boyu Wang 在此对 Boyu Wang 对本文所作的贡献表示诚挚感谢&#xff0c;他在武汉大学完成了数据科学与大数据技术专业的学习。擅长 R 语言、Python、机器学习、数据可视化。 中国短视频行业在经历爆发式增…

配置NGINX

Nginx环境配置与前端VUE部署安装nginx&#xff1a;命令sudo yum update && sudo yum install nginx部署:拷贝前端到目录/home/publish/idasweb/下修改nginx配置&#xff1a;进入到/etc/nginx目录下&#xff0c;修改nginx.conf中user www-data为user root&#xff0c;不…

MySQL深度理解-MySQL索引优化

1.Order by与Group by优化1.1Case1employees表中建立了name&#xff0c;position和age索引&#xff0c;并且使用了order by age进行排序操作&#xff1a;EXPLAIN SELECT * FROM employees WHERE name LiLei and position dev order by age最终explain的结果发现使用了idx_nam…

「Linux命令基础」用户和用户组实训

用户与用户组关系管理 在Linux系统中,用户和用户组的关系就像班级里的学生和小组。一个用户可以同时属于多个组,这种灵活的成员关系为权限管理提供了便利。创建用户时,系统会自动生成一个与用户同名的主组,这个组会成为用户创建文件时的默认属组。 理解用户和用户组的关系…

Https以及CA证书

目录 1. 什么是 HTTPS 通信机制流程 证书验证过程 CA证书 浏览器如何校验证书合法性呢&#xff1f; 1. 什么是 HTTPS HTTP 加上加密处理和认证以及完整性保护后即是 HTTPS。 它是为了解决 HTTP 存在的安全性问题&#xff0c;而衍生的协议&#xff0c;那使用 HTTP 的缺点有…

数字图像处理(四:图像如果当作矩阵,那加减乘除处理了矩阵,那图像咋变):从LED冬奥会、奥运会及春晚等等大屏,到手机小屏,快来挖一挖里面都有什么

数字图像处理&#xff08;四&#xff09;三、&#xff08;准备工作&#xff1a;玩具咋玩&#xff09;图像以矩阵形式存储&#xff0c;那矩阵一变、图像立刻跟着变&#xff1f;原图发挥了钞能力之后的图上述代码包含 10 个图像处理实验&#xff0c;每个实验会生成对应处理后的图…