实用指南:网络编程套接字

news/2026/1/11 16:12:45/文章来源:https://www.cnblogs.com/gccbuaa/p/19447398

先赞后看,养成习惯!!! ^ _ ^ ❤️ ❤️ ❤️

码字不易,大家的支持就是我坚持下去的动力,点赞后不要忘记关注我哦

本系列文章为本人在学习路上遇到的问题和解决方法,在这里撰写成文是为了巩固知识和帮助其他友友。

个人主页 :加瓦糕手

专栏链接 :问题分析简介

如有错误,请您指正批评 ^ _ ^

1. 网络编程基础

为什么需要网络编程?-丰富的网络资源

用户在浏览器中,打开在线视频网站,如优酷看视频,实质是通过网络,获取到网络上的一个视频资源。

与本地打开视频文件类似,只是视频文件这个资源的来源是网络。

相比本地资源来说,网络提供了更为丰富的网络资源:

所谓的网络资源,其实就是在网络中可以获取的各种数据资源。

而所有的网络资源,都是通过网络编程来进行数据传输的。

1.1 什么是网络编程?

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

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

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

进程A:编程来获取网络资源。

进程B:变成来提供网络资源。

1.2 网络中的基本概念

发送端和接收端

再一次网络传输时:

发送端:数据的发送送进程,称为发送端。发送端主机即网络通信中的源主机。

接收端:数据的接收收进程,称为接收端。接收端主机即网络通信中的目的主机。

收发端:发送端和接收端两端,也简称为收发端。

注意:发送端和接收端只是相对的,只是一次网络数据传输产生数据流向后的概念。

请求和响应:

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

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

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

客户端和服务端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。

客户端:获取服务的一方进程,称为客户端。

对于服务来说,一般是提供:

客户端获取服务资源:

客户端保存资源在服务端:

常见的客户端服务端模型

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

1. 客户端先发送请求到服务端

2. 服务端根据请求数据,执行相应的业务处理

3. 服务端返回响应:发送业务处理结果

4. 客户端根据响应数据,展示处理结果(展示获取的资源,或提示保存资源的处理结果)

2. Socket套接字

2.1 概念

Socket套接字,是系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。(相当于提供一个Socket接口,用户可以通过Socke套接字来实现send、receive数据)。

2.2 分类

Socket套接字主要针对传输层协议划分为如下三类:

流套接字:使用传输层TCP协议。

TCP即传输控制协议,传输层协议。

以下为TCP的特点:

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

数据报套接字:使用传输层UDP协议。

UDP即用户数据报协议,传输层协议。

以下为UDP的特点:

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

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

原始套接字:原始套接字用于自定义传输层协议,用于读写内核没有处理的IP协议数据。

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

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

java中使用UDP协议通信,主要基于DatagramSocket 类来创建数据报套接字,并使用DatagramPacket 作为发送或接收的UDP数据报。对于一次发送及接收UDP数据报的流程如下:

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

2.4 Java流套接字通信模型

3. UDP数据报套接字编程

API介绍

DatagramSocket

DatagramSocket是UDP Socket,用于发送和接收UDP数据报。

DatagramSocket构造方法:

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)。
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)

DatagramSocket方法:

方法签名方法说明
void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p)从此套接字发送数据报(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

DatagramPacket

DatagramPacket 是UDP Socket发送和接收的数据报。

DatagramPacket 构造方法:

方法签名方法说明
DatagramPacket(byte[] buf, int length)构造⼀个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)
DatagramPacket(byte[] buf, int offset,int length, SocketAddress address)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定长度(第二个参数length)。address指定目的主机的IP 和端口号。

DatagramPacket 方法:

方法签名方法说明
InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址。
int getPort()从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号。
byte[] getData() 获取数据报中的数据。

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

InetSocketAddress

InetSocketAddress(SocketAddress的子类)构造方法

方法签名方法说明
InetSocketAddress(InetSocketAddress addr,int port)创建一个Socket地址,包含IP地址和端口号

3.1 代码示例

UDP Echo Server

package network;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.Proxy;
import java.net.SocketException;
public class EchoServer {private DatagramSocket socket;public EchoServer(int port) throws SocketException {socket=new DatagramSocket(port);}//启动服务器,完成主要的业务逻辑public void start() throws IOException {System.out.println("服务端启动");while (true){// 1. 读取请求并解析//  1) 创建一个空白的 DatagramPacket 对象DatagramPacket reqPacket=new DatagramPacket(new byte[4096],4096);//  2) 通过 receive 读取网卡的数据. 如果网卡没有收到数据, 就会阻塞等待.socket.receive(reqPacket);//  3) 把 DatagramPacket 中的数据解析成字符串. 只需要从 DatagramPacket 取到有效的数据即可.String request=new String(reqPacket.getData(),0,reqPacket.getLength());//2.计算响应String response= process(request);//3.写回到客户端DatagramPacket resPacket=new DatagramPacket(response.getBytes(),response.getBytes().length,reqPacket.getSocketAddress());socket.send(resPacket);// 4. 打印日志.System.out.printf("[%s:%d] req: %s, resp: %s\n",reqPacket.getAddress(), reqPacket.getPort(), request, response);}}//回显服务器public String process(String request){return request;}public static void main(String[] args) throws IOException {EchoServer server=new EchoServer(9090);server.start();}
}

UDP Echo Client

package network;
import java.io.IOException;
import java.net.*;
import java.util.Scanner;
public class EchoClient {private DatagramSocket socket=null;private String serverIp;private int serverPort;public EchoClient(String serverIp, int serverPort) throws SocketException {this.serverIp = serverIp;this.serverPort = serverPort;socket = new DatagramSocket();}public void start() throws IOException {Scanner scanner=new Scanner(System.in);System.out.println("客户端启动!");while (true){System.out.print(">");String request=scanner.next();DatagramPacket reqPacket=new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),serverPort);socket.send(reqPacket);//3.读取服务器的响应DatagramPacket respPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(respPacket);String response=new String(respPacket.getData(),0,respPacket.getLength());// 4. 把响应显示到控制台.System.out.println(response);}}public static void main(String[] args) throws IOException {EchoClient client=new EchoClient("127.0.0.1",9090);client.start();}
}

UDP Dict Server

编写一个英译汉的服务器。只需要重写process。

package network;
import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
public class DictServer extends EchoServer{private Map dict=new HashMap<>();public DictServer(int port) throws SocketException {super(port);dict.put("cat", "小猫");dict.put("dog", "小狗");dict.put("pig", "小猪");dict.put("bird", "小鸟");dict.put("sheep", "小羊");dict.put("cow", "小牛");dict.put("chicken", "小鸡");dict.put("rabbit", "小兔子");dict.put("fish", "小鱼");dict.put("wolf", "狼");dict.put("monkey", "猴子");dict.put("chicken", "小鸡");dict.put("fish", "小鱼");dict.put("tiger", "老虎");dict.put("lion", "狮子");dict.put("wolf", "狼");dict.put("monkey", "猴子");}@Overridepublic String process(String request){return dict.getOrDefault(request,"该单词没有查到");}public static void main(String[] args) throws IOException {DictServer server=new DictServer(9090);server.start();}
}

4. TCP流套接字编程

API介绍

ServerSocket

ServerSocket 是创建TCP服务端Socket的API。

ServerSocket 构造方法:

方法签名方法说明
ServerSocket(int port)创建一个服务端套接字Socket,并绑定到指定端口

ServerSocket 方法:

方法签名方法说明
Socket accept()开始监听指定端⼝(创建时绑定的端⼝),有客户端连接后,返回⼀个服务端Socket对象,并基于该 Socket建立与客户端的连接,否则阻塞等待。
void close()关闭此套接字。

Socket

Socket 是客户端Socket,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服 务端Socket。

不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

Socket 构造方法:

方法签名方法说明
Socket(String host,int port)

创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接。

Socket 方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

4.1 代码示例

TCP Echo Server

package network.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;
public class EchoServer {private ServerSocket serverSocket;public EchoServer(int port) throws IOException {serverSocket=new ServerSocket(port);}public void start() throws IOException {Socket socket=serverSocket.accept();processConnection(socket);}private void processConnection(Socket socket){System.out.printf("[%s:%d] 服务器上线!\n", socket.getInetAddress().toString(), socket.getPort());try (InputStream inputStream=socket.getInputStream();OutputStream outputStream=socket.getOutputStream()){// 实现通信的代码.// 一个客户端可能会和服务器有多轮的请求响应交互.Scanner scanner=new Scanner(inputStream);PrintWriter writer=new PrintWriter(outputStream);while (true){if (!scanner.hasNext()){// 针对客户端下线逻辑的处理. 如果客户端断开连接了 (比如客户端结束了)// 此时 hasNext 就会返回 false// 如果是使用 read 方法, 就会出现返回 -1 的情况. 也可以用来判定客户端断开连接.System.out.printf("[%s:%d] client offline!\n", socket.getInetAddress().toString(), socket.getPort());break;}String request=scanner.next();String response=process(request);writer.println(response);writer.flush();System.out.printf("[%s:%d] req: %s; resp: %s\n", socket.getInetAddress().toString(), socket.getPort(),request, response);}} catch (IOException e) {e.printStackTrace();} finally {try {socket.close();} catch (IOException e) {e.printStackTrace();}}}private String process(String request) {return request;}public static void main(String[] args) throws IOException {EchoServer server=new EchoServer(9090);server.start();}
}

TCP Echo Client

package network.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;
public class EchoClient {private Socket socket;public EchoClient(String serverIp,int serverPort) throws IOException {// 在 new 这个对象的时候就涉及到 "建立连接操作"// 由于连接建立好了之后, 服务器的信息就在操作系统中被 TCP 协议记录了. 我们在应用程序层面上就不需要保存 IP 和 端口.socket = new Socket(serverIp, serverPort);}public void start(){System.out.println("客户端启动");Scanner scanner=new Scanner(System.in);try (InputStream inputStream = socket.getInputStream();OutputStream outputStream = socket.getOutputStream()) {Scanner scannerNet=new Scanner(inputStream);PrintWriter writer=new PrintWriter(outputStream);while (true){// 1. 从控制台读取用户的输入.System.out.print("> ");String request=scanner.next();writer.println(request);writer.flush();if (!scannerNet.hasNext()) {System.out.println("server disconnect");break;}String response=scannerNet.next();System.out.println(response);}} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) throws IOException {EchoClient client=new EchoClient("127.0.0.1",9090);client.start();}
}

5. 服务器引入多线程

如果只是单个线程,无法同时响应多个客户端。

此处给每个客户端都分配一个线程。

  public void start() throws IOException {System.out.println("服务器启动");while (true){Socket socket=serverSocket.accept();Thread t=new Thread(()->{processConnection(socket);});t.start();}}

5.1 服务器引入线程池

// 启动服务器
public void start() throws IOException {System.out.println("服务器启动!");ExecutorService service = Executors.newCachedThreadPool();while (true) {Socket clientSocket = serverSocket.accept();// 使⽤线程池, 来解决上述问题service.submit(new Runnable() {@Overridepublic void run() {processConnection(clientSocket);}});}
}

6. 长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接:

短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。

长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

对比以上长短连接,两者区别如下:

建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要 第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时 的,长连接效率更高。

主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送 请求,也可以是服务端主动发。

两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于 客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

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

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

相关文章

AI Agent输出质量不稳定?揭秘自我优化技巧,让AI Agent自己“回头看”,提升性能!

简介 反思模式(Reflection Pattern)通过Producer-Critic模型实现AI Agent的自我评估与迭代优化&#xff0c;将一次性输出升级为迭代改进。该方法适用于代码生成、内容创作、数据分析等场景&#xff0c;通过职责分离避免认知偏见&#xff0c;设置合理的迭代上限和停止条件&…

CAS号:855751-82-5,CO荧光探针,一氧化碳荧光探针

CAS号&#xff1a;855751-82-5&#xff0c;CO荧光探针&#xff0c;一氧化碳荧光探针CAS号 855751-82-5 的 CO 荧光探针是一类专门用于检测一氧化碳&#xff08;CO&#xff09;的功能分子&#xff0c;能够通过荧光信号的变化实现对 CO 的高灵敏检测。这类探针在化学生物学研究中…

【收藏必备】从零开始学RAG:嵌入模型如何提升大模型应用效果

Augmented Generation&#xff08;RAG&#xff09;眼下是构建生成式 AI 应用最火热的框架。企业和组织之所以钟爱它&#xff0c;是因为它能利用自身的专有数据来回答用户问题&#xff0c;使得大模型给出的答案更准确、最新且与问题高度相关。 根据我构建 RAG 应用的经验&#x…

日子过得真快

public class TestStudent { public static void main(String[] args) { // 方式1:使用无参构造创建对象,再赋值 Student stu1 = new Student(); stu1.name = "张三"; stu1.age = 18; stu1.showInfo(); st…

2026年1月国内比较好的消防泵公司综合推荐榜单 - 2026年企业推荐榜

文章摘要 随着智慧城市建设和消防安全的日益重要,消防泵技术已成为保障城市安全的核心驱动力。本文基于资本资源、技术产品、服务交付等六大维度,精选6家国内顶尖消防泵企业。榜单排名不分先后,旨在为各类企业提供多…

(Falco规则性能优化秘籍):让检测效率提升90%的配置策略

第一章&#xff1a;Falco规则性能优化的核心价值在现代云原生环境中&#xff0c;安全监控工具的实时性与资源效率直接影响系统的稳定性和可观测性。Falco 作为开源的运行时安全检测引擎&#xff0c;依赖规则匹配机制来识别异常行为。然而&#xff0c;随着规则数量增长和系统调用…

产品质量缺陷溯源:逆向推导生产环节中的问题点

VibeThinker-1.5B&#xff1a;轻量模型如何实现高精度推理&#xff1f; 在AI大模型军备竞赛愈演愈烈的今天&#xff0c;一个仅15亿参数的小型语言模型却悄然在数学与编程推理领域崭露头角——VibeThinker-1.5B。它没有千亿级参数的庞大规模&#xff0c;也未依赖海量算力训练&a…

深度测评2026 TOP10 AI论文平台:本科生毕业论文必备工具推荐

深度测评2026 TOP10 AI论文平台&#xff1a;本科生毕业论文必备工具推荐 2026年AI论文平台测评&#xff1a;为何需要一份权威榜单&#xff1f; 随着人工智能技术在学术领域的深入应用&#xff0c;越来越多的本科生开始依赖AI工具辅助毕业论文写作。然而&#xff0c;面对市场上琳…

VGGT(Visual Geometry Grounded Transformer)分析

1. 核心定位与创新价值1.1 核心目标提出一种前馈式神经网络&#xff0c;从单张、多张甚至数百张场景图像中&#xff0c;直接推断所有关键 3D 属性&#xff08;相机内参 / 外参、深度图、点云图、3D 点轨迹&#xff09;&#xff0c;无需依赖复杂的后处理优化&#xff08;如 bund…

【课程5.1】城管住建核心功能需求分析:市政设施、市容秩序等场景痛点拆解

严格基于指定城管住建相关文件&#xff08;核心为《06行业应用系统功能设计-01城管住建.docx》&#xff0c;简称《06-01城管》&#xff1b;《01智慧城市一网统管平台-系统总体架构及其功能要点-20251018修订.docx》&#xff0c;简称《01总体架构》&#xff1b;《03智慧城市一网…

2026年杭州靠谱高性价比茶叶店排名,茶叶店服务帮我推荐精选好茶商家推荐 - 工业品网

为帮茶客高效锁定适配自身需求的茶叶选购渠道,避免踩溢价虚高品质参差服务敷衍的坑,我们从茶品正宗度(核心产区溯源、工艺把控)、质价比优势(价格透明性、包装实用性)、服务专业度(选茶指导、售后保障)及真实客…

残疾人就业支持:帮助特殊群体掌握AI增强工作技能

残疾人就业支持&#xff1a;让AI成为特殊群体的职业加速器 在一场编程训练营的角落里&#xff0c;一位视障青年正通过耳机聆听语音助手逐行朗读代码逻辑。他没有使用任何商业云服务&#xff0c;设备只是一台搭载普通显卡的二手笔记本——支撑这一切的&#xff0c;是一个仅15亿参…

微信公众号推文精选:企业如何借力VibeThinker降本增效

微信公众号推文精选&#xff1a;企业如何借力VibeThinker降本增效 在AI模型越来越“大”的时代&#xff0c;反而有一类小而精的模型开始崭露头角——它们不追求千亿参数的堆砌&#xff0c;也不靠海量数据“暴力出题”&#xff0c;而是专注于把一件事做到极致&#xff1a;逻辑推…

2026年纯铝材料企业年度排名:松上1060铝卷的售后保障、应用案例与信任度深度解析 - 工业设备

在工业制造的材料基石领域,纯铝材料的品质、服务与适配性直接决定下游企业的生产效率与产品竞争力。2025年,随着新能源、建筑装饰、电子电器等行业的爆发式增长,市场对高纯度、全规格纯铝的需求持续攀升。面对众多供…

2026口碑好的十大旅行社年度排名:靠谱旅行社推荐,甄选有名的旅行社助力品质出行 - 工业设备

随着旅游市场复苏,2024年国内旅游人次突破60亿,北京作为文化古都,地接需求同比激增58%。但行业乱象频发:32%的游客遭遇低价团强制消费,41%的异地组团方因资源不足导致行程缩水,28%的研学团队因讲解不专业影响体验…

2026史上最全java面试题题库大全800题含答案

**一、 Java并发编程基础** 1.谈谈你对AQS的理解 2.lock和synchronized区别 3.线程池如何知道一个线程的任务已经执行完成 4.什么叫做阻塞队列的有界和无界 5.ConcurrentHashMap 底层具体实现知道吗&#xff1f;实现原理是什么&#xff1f; 6.能谈一下CAS机制吗&#xff…

2025专业粉粒体气力输送设备定制厂家TOP5权威推荐:甄选可靠制造厂 - 工业推荐榜

在工业生产自动化与环保升级的浪潮下,粉粒体气力输送设备作为化工、医药、锂电等行业的核心基建,市场需求持续攀升。据行业调研数据显示,2024年国内粉粒体输送设备市场规模突破120亿元,年增速达32%,但超28%的企业…

注意!手机NFC功能不用时务必关闭。诈骗分子常冒充客服诱导开启NFC盗刷资金、泄露信息,危害极大。需牢记“三不”原则,规范使用习惯,严控信息暴露,遇异常及时冻结账户并报警。‌‌=中国团队攻克超临界二氧

中国团队攻克超临界二氧化碳发电世界级难题&#xff0c;全球首台商用机组“超碳一号”在贵州投运。技术领先国际五年&#xff0c;效率高且节能环保&#xff0c;推动能源技术革新。‌‌1技术原理与优势‌介质替代‌&#xff1a;以超临界二氧化碳取代传统水蒸气&#xff0c;通过加…

农村学校远程教育:通过低带宽部署享受优质AI资源

农村学校远程教育&#xff1a;通过低带宽部署享受优质AI资源 在云南怒江峡谷深处的一所乡村中学&#xff0c;数学老师李明正为即将到来的信息学奥赛辅导课发愁。班上只有两台能联网的旧笔记本电脑&#xff0c;网络时断时续&#xff0c;平均下载速度不到50KB/s。他原本寄希望于…

老年大学兴趣班尝试:退休工程师玩转AI模型

老年大学兴趣班尝试&#xff1a;退休工程师玩转AI模型 在杭州一所普通老年大学的计算机教室里&#xff0c;几位白发学员正围坐在一台显示器前&#xff0c;轻声讨论着一段Python代码。他们不是程序员&#xff0c;而是平均年龄超过68岁的退休工程师——有人曾参与过卫星控制系统…