Java——网络编程套接字
目录
一、网络编程基础
1.1 为什么需要网络编程?——丰富的网络资源
二、什么是网络编程?
三、网络编程中的基本概念
3.2 请求和响应
3.3 客户端和服务端
常见的客户端服务端模型
四、Socket套接字
五、通信模型
5.1 Java数据报套接字通信模型
5.2 Java流套接字通信模型
Socket编程注意事项
5.3 UDP数据报套接字编程
示例一:
示例二:
一、网络编程基础
1.1 为什么需要网络编程?——丰富的网络资源
与本地打开视频文件类似,只是视频文件这个资源的来源是网络。
所谓的网络资源,其实就是在网络中可以获取的各种数据资源。
二、什么是网络编程?
- 进程A:编程来获取网络资源
- 进程B:编程来提供网络资源
三、网络编程中的基本概念
3.1 发送端和接收端
在一次网络数据传输时:
3.2 请求和响应
- 第一次:请求数据的发送
- 第二次:响应数据的发送。
好比在快餐店点一份炒饭:先要发起请求:点一份炒饭,再有快餐店提供的对应响应:提供一份炒饭
3.3 客户端和服务端
- 客户端获取服务资源
- 客户端保存资源在服务端
好比在银行办事:银行提供存款服务:用户(客户端)保存资源(现金)在银行(服务端)银行提供取款服务:用户(客户端)获取服务端资源(银行替用户保管的现金)
常见的客户端服务端模型
最常见的场景,客户端是指给用户使用的程序,服务端是提供用户服务的程序:
四、Socket套接字
- 有连接
- 可靠传输
- 面向字节流
- 有接收缓冲区,也有发送缓冲区
- 大小不限
对于字节流来说,可以简单的理解为,传输数据是基于 IO 流,流式数据的特征就是在 IO 流没有关闭的情况下,是无边界的数据,可以多次发送,也可以分开多次接收。
- 无连接
- 不可靠传输
- 面向数据报
- 有接收缓冲区,无发送缓冲区
- 大小受限:一次最多传输64k
对于数据报来说,可以简单的理解为,传输数据是一块一块的,发送一块数据假如 100 个字节,必须一次发送,接收也必须一次接收100 个字节,而不能分 100 次,每次接收 1 个字节。
4.3 原始套接字
五、通信模型
5.1 Java数据报套接字通信模型
5.2 Java流套接字通信模型

Socket编程注意事项

此时需要检查进程B绑定的是哪个端口,再查看该端口被哪个进程占用。以下为通过端口号查进程的方式:
- 在cmd输入 netstat -ano | findstr 端口号 ,则可以显示对应进程的pid。如以下命令显
- 在任务管理器中,通过pid查找进程

解决端口被占用的问题:
- 如果占用端口的进程A不需要运行,就可以关闭A后,再启动需要绑定该端口的进程B
- 如果需要运行A进程,则可以修改进程B的绑定端口,换为其他没有使用的端口。
5.3 UDP数据报套接字编程
DatagramSocket API
DatagramSocket 方法:

DatagramPacket API

DatagramPacket 方法:

构造UDP发送的数据报时,需要传入 SocketAddress ,该对象可以使用 InetSocketAddress 来创
示例一:
实现一个基于TCP的回显服务
客户端:
mport 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 {// 定义一个用于客户端的Socket对象private Socket clientSocket;/*** 初始化客户端的Socket** @param serverIp 服务器IP地址* @param serverPort 服务器的端口号* @throws IOException*/public TCPEchoClient (String serverIp, int serverPort) throws IOException {this.clientSocket = new Socket(serverIp, serverPort);}public void start () throws IOException {System.out.println("客户端已启动...");// 获取Socket中的输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的输入while (true) {System.out.println("->");// 接收用户的输入内容Scanner requestScanner = new Scanner(System.in);String request = requestScanner.nextLine();// 发送用户的请求PrintWriter printWriter = new PrintWriter(outputStream);printWriter.println(request);// 强制刷新缓冲区printWriter.flush();// 接收服务器的响应Scanner responseScanner = new Scanner(inputStream);// 获取响应数据String response = responseScanner.nextLine();// 打印响应内容System.out.println("接收到服务器的响应:" + response);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}public static void main(String[] args) throws IOException {TCPEchoClient client = new TCPEchoClient("127.0.0.1", 9999);client.start();}
} 服务端:
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ProtocolException;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.MessageFormat;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;/*** 基于TCP的服务器程序* @Date 2023-05-23*/
public class TCPEchoServer {// 声明一个用于服务端的Socket对象private ServerSocket server;/*** 通过指定端口号实例化服务** @param port 端口号* @throws IOException*/public TCPEchoServer(int port) throws IOException {if (port < 1025 || port > 65535) {throw new RuntimeException("端口号要在 1025 ~ 65535之间.");}// 实例化ServerSocket并指定端口号this.server = new ServerSocket(port);}public void start() throws IOException {System.out.println("服务器启动成功...");// 创建一个线程池ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(3, 10, 1, TimeUnit.SECONDS,new LinkedBlockingQueue<>(10));// 循环接收客户端的连接while (true) {Socket clientSocket = server.accept();// 每接收到一个新连接请求,就创建一个新的子线程
// Thread thread = new Thread(() -> {
// // 处理Socket中的数据
// try {
// processConnections(clientSocket);
// } catch (IOException e) {
// e.printStackTrace();
// }
// });
// // 启动线程
// thread.start();// 提交任务到线程池中poolExecutor.submit(() -> {try {processConnections(clientSocket);} catch (IOException e) {e.printStackTrace();}});}}// 处理数据private void processConnections(Socket clientSocket) throws IOException {// 打印日志String clientInfo = MessageFormat.format("[{0}:{1}] 客户端已上线", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);// 处理数据之前要获取一下输入输出流try (InputStream inputStream = clientSocket.getInputStream();OutputStream outputStream = clientSocket.getOutputStream()) {// 循环处理用户的请求while (true) {// 通过Scanner读取用户请求中的数据Scanner requestScanner = new Scanner(inputStream);if (!requestScanner.hasNextLine()) {// 日志clientInfo = MessageFormat.format("[{0}:{1}] 客户端已下线.", clientSocket.getInetAddress(),clientSocket.getPort());System.out.println(clientInfo);break;}// 获取真实的用户请求数据String request = requestScanner.nextLine();// 根据请求计算响应String response = process(request);// 把响应写回客户端PrintWriter printWriter = new PrintWriter(outputStream);// 写入输出流printWriter.println(response);// 强制刷新缓冲区printWriter.flush();// 打印日志clientInfo = MessageFormat.format("[{0}:{1}], request: {2}, response: {3}",clientSocket.getInetAddress(), clientSocket.getPort(), request, response);System.out.println(clientInfo);}} catch (IOException e) {e.printStackTrace();} finally {clientSocket.close();}}private String process(String request) {System.out.println("收到新消息:" + request);Scanner scanner = new Scanner(System.in);String response = scanner.nextLine();return response;}public static void main(String[] args) throws IOException {TCPEchoServer server = new TCPEchoServer(9999);server.start();}
}
示例二:
实现一个基于UDP的回显服务:
客户端:
import java.io.IOException;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;/*** @Date 2023-05-20*/
public class UDPEchoClient {// 定义一个用于客户端的DatagramSocketprivate DatagramSocket client;// 定义服务器的IP地址private String serverIp;// 定义服务器的端口号private int port;private SocketAddress address;/*** 构造方法,指定服务器的Ip地址和端口号** @param serverIp 服务器IP* @param port 端口号*/public UDPEchoClient (String serverIp, int port) throws SocketException {this.client = new DatagramSocket();this.serverIp = serverIp;this.port = port;this.address = new InetSocketAddress(serverIp, port);}public void start () throws IOException {System.out.println("客户端已启动.");// 循环接收用户的输入Scanner scanner = new Scanner(System.in);while (true) {System.out.println("->");// 接收用户输入String request = scanner.next();// 1. 把请求内容包装成DatagramPacketDatagramPacket requestPacket = new DatagramPacket(request.getBytes(StandardCharsets.UTF_8),request.getBytes().length, address);// 2. 发送数据client.send(requestPacket);// 3. 接收响应DatagramPacket responsePacket = new DatagramPacket(new byte[1024], 1024);// 4. 在receive方法中填充响应数据client.receive(responsePacket);// 5. 解析响应数据String response = new String(responsePacket.getData(), 0, responsePacket.getLength(), "UTF-8");// 6. 打印日志System.out.printf("request: %s, response: %s.\n", request, response);}}public static void main(String[] args) throws IOException {UDPEchoClient client = new UDPEchoClient("127.0.0.1", 9999);// 启动服务client.start();}}
服务端:
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.nio.charset.StandardCharsets;/*** UDP 回显服务器** @Date 2023-05-20*/
public class UDPEchoServer {// 定义一个用于服务器端的DatagramSocketprivate DatagramSocket server;/*** 构造方法,完成服务器的初始化* @param port 端口号*/public UDPEchoServer (int port) throws Exception {if (port > 65535 || port < 1024) {throw new Exception("端口号必须在1024 ~ 65535之间");}// 初始化服务器端的UDP服务this.server = new DatagramSocket(port);}/*** 对外提供服务*/public void start () throws IOException {System.out.println("服务器已启动....");// 循环接收用户的请求while (true) {// 1. 创建一个用于接收请求数据的DatagramPacketDatagramPacket requestPacket = new DatagramPacket(new byte[1024], 1024);// 2. 接收请求, 把真实的内容填充到requestPacketserver.receive(requestPacket);// 3. 从requestPacket获取数据String request = new String(requestPacket.getData(), 0, requestPacket.getLength(), "UTF-8");// 4. 根据请求获取响应String response = processor (request);// 5. 把响应封装到DatagramPacketDatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),response.getBytes().length, requestPacket.getSocketAddress());// 6. 发送数据server.send(responsePacket);// 7. 打印日志System.out.printf("[%s:%d] request: %s, response: %s.\n", requestPacket.getAddress().toString(),requestPacket.getPort(), request, response);}}public String processor(String request) {return request;}public static void main(String[] args) throws Exception {// 初始化服务器UDPEchoServer server = new UDPEchoServer(9999);// 启动服务server.start();}}
简单的字典功能
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;/*** @Date 2023-05-20*/
public class UDPDictServer extends UDPEchoServer{private Map<String, String> map = new HashMap<>();/*** 构造方法,完成服务器的初始化** @param port 端口号*/public UDPDictServer(int port) throws Exception {super(port);// 初始化字典内容map.put("dog", "小狗");map.put("cat", "小猫");map.put("pig", "小猪");map.put("tiger", "大老虎");map.put("veryGood", "牛P");}@Overridepublic String processor(String request) {return map.getOrDefault(request, "查无此词");}public static void main(String[] args) throws Exception {UDPDictServer server = new UDPDictServer(9999);server.start();}
} 相关文章:
Java——网络编程套接字
目录 一、网络编程基础 1.1 为什么需要网络编程?——丰富的网络资源 二、什么是网络编程? 三、网络编程中的基本概念 3.2 请求和响应 3.3 客户端和服务端 常见的客户端服务端模型 四、Socket套接字 五、通信模型 5.1 Java数据报套接字通信模型 5.2 Java流…...
160套小程序源码
源码列表如下: AppleMusic (知乎日报) 微信小程序 d artand 今日更新求职招聘类 医药网 口碑外卖点餐 城市天气 外卖小程序 定位天气 家居在线 微信小程序-大好商城,wechat-weapp 微信小程序的掘金信息流 微信跳一跳小游戏源码 微票源码-demo 急救应急处…...
有效项目进度管理的 10 条规则
项目进度管理是项目中比较关键的方面之一,因为它将决定事情的进展方式、进展速度以及是否会取得进展。换句话说,它可以让你较好地控制项目,帮助你预测不可预测的情况,并使所有相关团队能够高效地协同工作。 以下是有效项目进度管…...
javaWebssh服装租赁店信息管理系统台myeclipse开发mysql数据库MVC模式java编程计算机网页设计
一、源码特点 java ssh服装租赁店信息管理系统是一套完善的web设计系统(系统采用ssh框架进行设计开发),对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要 采用B/S模式开发。开发环境为TO…...
概率论:样本与总体分布,Z分数与概率
参考书目:《行为科学统计精要》(第八版)——弗雷德里克J格雷维特 数据及其样本的分布 描述一组数据分布 描述一组样本数据的分布 描述样本数据的均值和整体数据一样,但是样本标准差的公式除以了n-1,这里引入自由度的…...
【JavaSE】Java基础语法(十二):ArrayList
文章目录 1. ArrayList的构造方法和添加方法2. ArrayList类常用方法3. ArrayList存储学生对象并遍历 集合和数组的区别 : 共同点:都是存储数据的容器不同点:数组的容量是固定的,集合的容量是可变的 1. ArrayList的构造方法和添加方法 ArrayL…...
c++—封装:运算符重载、友元
1. 友元 (1)友元函数 ①是一种允许非类成员函数访问类的私有成员的一种机制;可以把一个函数指定为类的友元,也可以把整个类指定为另一个类的友元; ②友元函数在类作用域外定义,但需要在类体中进行声明&…...
【K8s】安全认证与DashBoard
文章目录 一、概述1、客户端2、认证、鉴权与准入控制 二、认证管理1、认证方式2、HTTPS证书认证 三、授权管理1、授权与RBAC2、Role 与 ClusterRole3、RoleBinding 与 ClusterRoleBinding4、案例:创建一个只能管理dev空间下Pods资源的账号 四、准入控制五、DashBoar…...
SpringMVC第七阶段:SpringMVC的增删改查(01)
SpringMVC的增删改查 1、准备单表的数据库 drop database if exists springmvc;create database springmvc;use springmvc; ##创建图书表 create table t_book(id int(11) primary key auto_increment, ## 主键name varchar(50) not null, ## 书名 author varchar(50) no…...
接口测试-Mock测试方法
一、关于Mock测试 1、什么是Mock测试? Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造出来)或者不容易获取的比较复杂的对象(如 JDBC 中的ResultSet 对象&#…...
关于宝塔部署jar包和war包
文章目录 前言一、jar包部署二、war包部署1.maven如果打包不了使用命令打包2.安装Tomcat进行访问是否成功2.进入Tomcat目录进行配置war包 一、项目访问方法 前言 提示:以下是本篇文章正文内容,下面案例可供参考 一、jar包部署 1.其实jar包没什么讲的&…...
SpringMVC框架面试专题(初级-中级)-第十节
欢迎大家一起探讨~如果可以帮到大家请为我点赞关注哦~ 截止到本节关于SpringMVC的内容已经更新完毕,后续会更新SpringBoot框架的面试题;大家在背题的时候切记不要死记硬背,需要理解 这是什么?有什么操作&a…...
PCIe TLB事务层详解过程
目录 1.What is TLP 2.PCIe 4种不同的事务 2.1.Memory事务 2.2.IO事务 2.3.Configuration事务 2.4.Message...
RK3588平台开发系列讲解(项目篇)YOLOv5部署测试
平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、YOLOv5环境安装二、YOLOv5简单使用2.1、获取预训练权重文2.2、YOLOv5简单测试2.3、转换为rknn模型2.4、部署到 RK 板卡三、airockchip/yolov5简单测试3.1、转换成rknn模型并部署到板卡沉淀、分享、成长,让自己和他…...
基于变形模板的弱监督体图像分割
文章目录 Weakly Supervised Volumetric Image Segmentation with Deformed Templates摘要本文方法实验结果 Weakly Supervised Volumetric Image Segmentation with Deformed Templates 摘要 背景 有许多方法可以对网络进行弱监督训练来分割2D图像。依赖于对3D图像的2D切片的…...
python实现单例模式及其应用
单例模式是一种常见的设计模式,它保证一个类只能被实例化一次,并提供了一个全局访问点来获取这个唯一的实例。 在 Python 中,可以通过使用装饰器、元类或模块等方式实现单例模式。下面分别介绍这三种方法: 1.使用装饰器实现单例…...
SSM 如何使用 Seata 框架实现分布式事务?
SSM 如何使用 Seata 框架实现分布式事务? 分布式事务是现代分布式系统中必不可少的一部分,而 Seata 框架是一种常用的分布式事务处理方式。在 SSM 框架中,我们可以使用 Seata 框架来管理分布式事务。本文将介绍如何在 SSM 框架中使用 Seata …...
FreeRTOS任务相关API函数
任务创建和删除API函数 xTaskCreate() 创建任务。RAM BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务函数const char* const pcName, //任务名字const uint16_t usStackDepth,//任务堆栈大小void * const …...
VBA之正则表达式(42)-- 提取代码中变量名称
实例需求:待处理代码段如下所示,现在需要提取其中的变量名称。 Public pFactor As Integer Sub TestCode() Dim reg As New RegExp, a As Workbook Dim ms As VBScript_RegExp_55.MatchCollection Dim m As VBScript_RegExp_55.Match Dim i, j Dim x1, y…...
Unity Lightmapping Setting
如下图: Lightmapper: 使用什么硬件或算法渲染 Progressive CPU、Progressive GPU、Enlighten(新的算放目前用的比较少) 此数值会被用于分别乘以Direct Samples,Indirect Samples和Environment Samples这三个数值。这三个数值会被应用于…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》
引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)
名人说:莫道桑榆晚,为霞尚满天。——刘禹锡(刘梦得,诗豪) 原创笔记:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 上一篇:《数据结构第4章 数组和广义表》…...
Tauri2学习笔记
教程地址:https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引:https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多,我按照Tauri1的教程来学习&…...
安宝特案例丨寻医不再长途跋涉?Vuzix再次以AR技术智能驱动远程医疗
加拿大领先科技公司TeleVU基于Vuzix智能眼镜打造远程医疗生态系统,彻底革新患者护理模式。 安宝特合作伙伴TeleVU成立30余年,沉淀医疗技术、计算机科学与人工智能经验,聚焦医疗保健领域,提供AR、AI、IoT解决方案。 该方案使医疗…...
