通信网络编程3.0——JAVA
主要添加了私聊功能
1服务器类定义与成员变量
public class ChatServer {int port = 6666;// 定义服务器端口号为 6666ServerSocket ss;// 定义一个 ServerSocket 对象用于监听客户端连接//List<Socket> clientSockets = new ArrayList<>();// 定义一个列表用于存储已连接的客户端 Socket 对象List<Socket> clientSockets = new CopyOnWriteArrayList<>();List<String> clientNames = new ArrayList<>(10);//迭代时会复制整个底层数组,因此在遍历过程中其他线程对集合的修改不会影响当前遍历,// 有效避免了 ConcurrentModificationException 异常。
}
- 端口号:服务器的端口号被定义为
6666
,客户端需要知道这个端口号才能与服务器建立连接。 - ServerSocket 对象:
ServerSocket
是 Java 提供的一种用于服务器端编程的类,它负责监听特定端口上的客户端连接请求。一旦有客户端连接,就会创建一个新的Socket
对象来处理与该客户端之间的通信。 - 客户端套接字列表:
clientSockets
使用了CopyOnWriteArrayList
来存储与客户端建立连接的Socket
对象。这种数据结构在遍历时会复制整个底层数组,因此在遍历过程中其他线程对集合的修改不会影响当前遍历,有效避免了ConcurrentModificationException
异常。 - 客户端名称列表:
clientNames
用于存储每个连接客户端的名称,方便在消息中区分不同的客户端。
2初始化服务器
public void initServer() {// 初始化服务器的方法try {ss = new ServerSocket(port);// 创建 ServerSocket 对象并绑定到指定端口System.out.println("服务器启动,等待客户端连接...");} catch (IOException e) {throw new RuntimeException(e);}}
- 在服务器初始化方法
initServer
中,通过调用ServerSocket
的构造函数并传入端口号,创建了一个ServerSocket
对象,绑定了服务器到指定端口,使服务器能够监听该端口上的客户端连接请求。一旦初始化成功,就会打印出 "服务器启动,等待客户端连接..." 的提示信息,告知服务器已正常启动并处于监听状态。
3监听客户端连接
public void listenerConnection() {// 监听客户端连接的方法,返回连接的 Socket 对象new Thread(()->{while(true){try {Socket socket = ss.accept();// 调用 accept() 方法等待客户端连接clientNames.add("Hello");//clientSockets.add(socket);synchronized (clientSockets) {// 同步操作确保线程安全clientSockets.add(socket);// 将连接的客户端 Socket 对象添加到列表中}System.out.println("客户端已连接:" + socket.getInetAddress().getHostAddress());// 输出客户端连接成功提示信息及客户端 IP 地址} catch (IOException e) {throw new RuntimeException(e);}}}).start();}
listenerConnection
方法创建了一个新线程,用于不断地监听客户端的连接请求。在循环中,调用ss.accept()
方法阻塞等待客户端的连接。一旦有客户端连接,就会创建一个新的Socket
对象,并将其添加到clientSockets
列表中。同时,向clientNames
列表中添加一个默认客户端名称 "Hello",后续可以根据实际情况更新该名称。每当有新的客户端连接成功,就会打印出客户端的 IP 地址,表明该客户端已成功连接到服务器。
4读取客户端消息
public void readMsg(List<Socket> clientSockets, JTextArea msgShow) {// 读取客户端消息的方法//System.out.println("clientSockets size: " + clientSockets.size()); // 检查列表大小synchronized (clientSockets) {// 对客户端列表进行同步操作Thread tt = new Thread(() -> {// 创建一个线程用于读取并处理客户端消息//System.out.println("开始读取客户端发送的消息");while (true) {// 无限循环持续读取消息InputStream is;// 定义输入流对象用于读取客户端消息Socket socket = null;try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}for (Socket cSocket : clientSockets) {// 遍历每个客户端 Socket//System.out.println("循环每个socket");socket = cSocket;if(socket == null){continue;}try {is = socket.getInputStream();// 获取客户端 Socket 对象的输入流} catch (IOException e) {throw new RuntimeException(e);}try {int idLen = is.read();// 读取消息中发送方名称长度的字节if(idLen == 0){continue;}byte[] id = new byte[idLen];// 根据读取的长度创建字节数组存储发送方名称is.read(id);// 读取发送方名称字节数组int si = clientSockets.indexOf(socket);clientNames.set(si,new String(id));int msgLen = is.read();// 读取消息内容长度的字节if(msgLen == 0){continue;}byte[] msg = new byte[msgLen];// 根据读取的长度创建字节数组存储消息内容is.read(msg);// 读取消息内容字节数组String clientmsg = new String(msg);//先判断@有没有int start = clientmsg.indexOf('@');if(start != -1){int end = clientmsg.indexOf(' ');String friendID = clientmsg.substring(start+1,end);String message = clientmsg.substring(end);System.out.println(new String(id) + "发送给" + friendID + " 的一条私聊消息:" + message);// 将字节数组转换为字符串并输出消息内容msgShow.append(new String(id) + "发送给" + friendID + " 的一条私聊消息:" + message + "\n");for (Socket clientSocket : clientSockets) {// 遍历所有已连接的客户端 Socket 对象if (clientSocket == socket) {// 如果是当前发送消息的客户端continue;}int s = clientSockets.indexOf(clientSocket);String name = clientNames.get(s);if(name.equals(friendID)){OutputStream os = null;// 定义输出流对象用于向其他客户端发送消息os = clientSocket.getOutputStream();// 获取客户端 Socket 对象的输出流os.write(id.length);// 发送发送方名称长度os.write(id);// 发送发送方名称字节数组message += "(这是一条私聊消息)";os.write(message.getBytes().length);// 发送消息内容长度os.write(message.getBytes());// 发送消息内容字节数组os.flush();// 刷新输出流确保数据发送完成break;}}}else {System.out.println(new String(id) + "发送的消息:" + new String(msg));// 将字节数组转换为字符串并输出消息内容msgShow.append(new String(id) + "说:" + new String(msg) + "\n");// 转发信息给所有其他客户端for (Socket clientSocket : clientSockets) {// 遍历所有已连接的客户端 Socket 对象if (clientSocket == socket) {// 如果是当前发送消息的客户端continue;}OutputStream os = null;// 定义输出流对象用于向其他客户端发送消息os = clientSocket.getOutputStream();// 获取客户端 Socket 对象的输出流os.write(id.length);// 发送发送方名称长度os.write(id);// 发送发送方名称字节数组os.write(msg.length);// 发送消息内容长度os.write(msg);// 发送消息内容字节数组os.flush();// 刷新输出流确保数据发送完成}}} catch (IOException e) {throw new RuntimeException(e);}}}});tt.start();}}
readMsg
方法的核心功能是读取客户端发送的消息,并根据消息类型(普通消息或私聊消息)进行相应的处理和转发。- 首先,创建一个新线程
tt
,在无限循环中依次检查clientSockets
列表中的每个Socket
对象。对于每个客户端Socket
,通过socket.getInputStream()
获取输入流,从而读取客户端发送的数据。 - 客户端发送的数据格式预先约定为:首先是一个字节表示发送方名称的长度,然后是发送方名称对应的字节数组;接下来是一个字节表示消息内容长度,最后是消息内容对应的字节数组。按照这种格式,先读取发送方名称长度
idLen
,根据该长度创建字节数组id
读取发送方名称,再读取消息内容长度msgLen
,创建字节数组msg
读取消息内容。 - 随后,将读取到的发送方名称更新到对应的
clientNames
列表位置。接下来对消息内容进行判断,如果消息内容中包含 "@" 符号,则认为这是一条私聊消息。通过解析消息内容,获取私聊目标的名称friendID
和实际消息内容message
,然后在clientSockets
中查找对应的私聊目标客户端Socket
,并将私聊消息发送给该目标客户端。 - 如果消息内容中不包含 "@" 符号,则认为这是一条普通消息,直接将消息转发给除发送方外的所有其他客户端。
- 无论是普通消息还是私聊消息,都通过输出流
OutputStream
将消息发送给目标客户端。发送时,同样按照约定的数据格式,先发送发送方名称的长度和名称字节数组,再发送消息内容的长度和内容字节数组,并调用os.flush()
刷新输出流确保数据发送完成。
5服务器启动
public void start() {// 启动服务器的方法initServer();// 调用初始化服务器的方法//new Thread(()->{//startSend();// 启动服务端从控制台向所有客户端发送消息的线程//}).start();ChatUI ui = new ChatUI("服务端", clientSockets);ui.setVisible(true); // 确保 UI 可见listenerConnection();// 调用监听客户端连接的方法readMsg(clientSockets,ui.msgShow);// 调用读取消息的方法}
- 在
start
方法中,首先调用initServer
方法初始化服务器,然后创建一个ChatUI
对象作为服务器端的用户界面(假设存在ChatUI
类,用于展示聊天内容等信息),使用户界面可见。接着调用listenerConnection
方法启动监听客户端连接的线程,最后调用readMsg
方法启动读取消息的线程,并将读取到的消息显示在用户界面中。
6主方法
public static void main(String[] args) {ChatServer server = new ChatServer();// 创建 ChatServer 对象server.start();// 调用启动服务器的方法}
main
方法作为程序的入口,创建了一个ChatServer
对象,并调用其start
方法启动服务器。
7其他模块代码不变
public class Client {Socket socket;// 定义 Socket 对象用于与服务器建立连接String ip;// 定义服务器 IP 地址int port;// 定义服务器端口号InputStream in;// 定义输入流对象用于读取服务器发送的消息OutputStream out;// 定义输出流对象用于向服务器发送消息public Client(String ip, int port) {// 构造方法,初始化客户端 IP 地址和端口号this.ip = ip;this.port = port;}public void connectServer(String userName) {// 连接服务器的方法try {socket = new Socket(ip, port);// 创建 Socket 对象连接到指定 IPin = socket.getInputStream();// 获取 Socket 对象的输入流用于读取消息out = socket.getOutputStream();// 获取 Socket 对象的输出流用于发送消息try {out.write(userName.length());out.write(userName.getBytes());out.flush();} catch (IOException e) {throw new RuntimeException(e);}System.out.println("连接服务器成功");} catch (IOException e) {throw new RuntimeException(e);}}public void readMsg(JTextArea msgShow) {// 读取服务器发送的消息的方法new Thread(() -> {// 创建一个线程用于读取并处理服务器消息try {System.out.println("开始读取消息");while (true) { // 无限循环持续读取消息int senderNameLength = in.read();// 读取发送方名称长度的字节byte[] senderNameBytes = new byte[senderNameLength];// 根据读取的长度创建字节数组存储发送方名称in.read(senderNameBytes);// 读取发送方名称字节数组int msgLength = in.read();// 读取消息内容长度的字节byte[] msgBytes = new byte[msgLength];// 根据读取的长度创建字节数组存储消息内容in.read(msgBytes);// 读取消息内容字节数组System.out.println(new String(senderNameBytes) + "发送的消息:" + new String(msgBytes));// 将字节数组转换为字符串并输出消息内容msgShow.append(new String(senderNameBytes) +"说:" + new String(msgBytes) + "\n");}} catch (IOException e) {throw new RuntimeException(e);}}).start();}/*public void startSend() {// 从控制台向服务器发送消息的方法new Thread(() -> {// 创建一个线程用于读取控制台输入并发送消息try {BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));// 创建缓冲读取器读取控制台输入System.out.println("请输入用户名:");String userName = reader.readLine();// 读取一行控制台输入作为用户名System.out.println("请输入消息(按回车发送):");while (true) {// 无限循环持续读取并发送消息String msg = reader.readLine();// 读取一行控制台输入作为消息内容if (msg != null && !msg.isEmpty()) {// 如果输入的消息不为空out.write(userName.getBytes().length);// 发送用户名长度out.write(userName.getBytes());// 发送用户名字节数组out.write(msg.getBytes().length);// 发送消息内容长度out.write(msg.getBytes());// 发送消息内容字节数组out.flush();// 刷新输出流确保数据发送完成}}} catch (IOException e) {throw new RuntimeException(e);}}).start();}*/public void startClient() {// 启动客户端的方法String userName = JOptionPane.showInputDialog("请输入用户名:");connectServer(userName);// 调用连接服务器的方法ChatUI ui = new ChatUI(userName, out);readMsg(ui.msgShow);// 调用读取消息的方法//startSend();// 调用发送消息的方法try {Thread.sleep(500);} catch (InterruptedException e) {throw new RuntimeException(e);}new Thread() {public void run() {while (true) {try {out.write(0);out.flush();Thread.sleep(500);} catch (IOException e) {throw new RuntimeException(e);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}.start();}public static void main(String[] args) {Client client = new Client("127.0.0.1", 6666);// 创建 Client 对象,连接到本地主机的 6666 端口client.startClient();// 调用启动客户端的方法}
}
public class ChatUI extends JFrame {public JTextArea msgShow = new JTextArea();// 显示消息的文本区域public ChatUI(String title, List<Socket> clientSockets) {// 服务器端构造方法super(title);// 设置窗口标题setSize(500, 500);// 设置窗口大小setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 设置关闭操作JScrollPane scrollPane = new JScrollPane(msgShow);// 创建滚动面板包括消息显示区域scrollPane.setPreferredSize(new Dimension(0, 350));add(scrollPane, BorderLayout.NORTH);// 添加到窗口北部// 创建消息输入面板及组件JPanel msgInput = new JPanel();JTextArea msg = new JTextArea();JScrollPane scrollPane1 = new JScrollPane(msg);scrollPane1.setPreferredSize(new Dimension(480, 80));msgInput.add(scrollPane1);JButton send = new JButton("发送");msgInput.add(send);msgInput.setPreferredSize(new Dimension(0, 120));add(msgInput, BorderLayout.SOUTH);// 添加到窗口南部setVisible(true);ChatListener cl = new ChatListener();// 创建事件监听器send.addActionListener(cl);// 为发送按钮添加监听器cl.showMsg = msgShow;// 传递消息显示组件cl.msgInput = msg;cl.userName = title;cl.clientSockets = clientSockets;}public ChatUI(String title, OutputStream out) {// 客户端构造方法super(title);setSize(500, 500);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);JScrollPane scrollPane = new JScrollPane(msgShow);scrollPane.setPreferredSize(new Dimension(0, 350));add(scrollPane, BorderLayout.NORTH);JPanel msgInput = new JPanel();JTextArea msg = new JTextArea();JScrollPane scrollPane1 = new JScrollPane(msg);scrollPane1.setPreferredSize(new Dimension(480, 80));msgInput.add(scrollPane1);JButton send = new JButton("发送");msgInput.add(send);msgInput.setPreferredSize(new Dimension(0, 120));add(msgInput, BorderLayout.SOUTH);setVisible(true);clientListener cl = new clientListener();send.addActionListener(cl);cl.showMsg = msgShow;cl.msgInput = msg;cl.userName = title;cl.out = out;}
}
public class ChatListener implements ActionListener {public List<Socket> clientSockets;// 客户端 Socket 列表JTextArea showMsg;// 消息显示区域JTextArea msgInput;// 消息输入区域String userName;// 用户名OutputStream out;// 输出流public void actionPerformed(ActionEvent e) {// 处理发送按钮点击事件String text = msgInput.getText();// 获取输入的消息文本showMsg.append(userName + ": " + text + "\n");// 在显示区域追加消息for (Socket cSocket : clientSockets) {// 遍历所有客户端Socket socket = cSocket;try {out = socket.getOutputStream();// 获取客户端输出流out.write(userName.getBytes().length);// 发送用户名长度out.write(userName.getBytes());// 发送用户名out.write(text.getBytes().length);// 发送消息内容长度out.write(text.getBytes());// 发送消息内容out.flush();// 刷新输出流} catch (IOException ex) {throw new RuntimeException(ex);}}}}
public class clientListener implements ActionListener {JTextArea showMsg;// 消息显示区域JTextArea msgInput;// 消息输入区域String userName;// 用户名OutputStream out;// 输出流public void actionPerformed(ActionEvent e) {// 处理发送按钮点击String text = msgInput.getText();// 获取输入消息showMsg.append(userName + ": " + text + "\n");// 显示消息try {out.write(userName.getBytes().length);// 发送用户名长度out.write(userName.getBytes());// 发送用户名out.write(text.getBytes().length);// 发送消息长度out.write(text.getBytes());// 发送消息内容out.flush();// 刷新输出流//msgInput.setText(""); // 清空输入框} catch (IOException ex) {throw new RuntimeException(ex);}}
}
8运行效果
相关文章:
通信网络编程3.0——JAVA
主要添加了私聊功能 1服务器类定义与成员变量 public class ChatServer {int port 6666;// 定义服务器端口号为 6666ServerSocket ss;// 定义一个 ServerSocket 对象用于监听客户端连接//List<Socket> clientSockets new ArrayList<>();// 定义一个列表用于存储…...
4-深度学习网络层
深度学习模型 Embedding层 Embedding矩阵是可训练的参数,一般会在模型构建时随机初始化 也可以使用预训练的词向量来做初始化,此时也可以选择不训练Embedding层中的参数 输入的整数序列可以有重复,但取值不能超过Embedding矩阵的列数 核心…...
【LeetCode】用双指针解决移除元素问题、合并两个有序数组求解
🔥个人主页:艾莉丝努力练剑 ❄专栏传送门:《C语言》、《数据结构与算法》、C语言刷题12天IO强训 🍉学习方向:C/C方向 ⭐️人生格言:为天地立心,为生民立命,为往圣继绝学,…...
车载诊断架构协议篇 --- OBDonUDS和ZEVonUDS
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从&#x…...
医学 Agent:自带医学深度调研 deep research,优化治疗策略+药物参考
医学 Agent:自带医学深度调研deep research,优化治疗策略药物参考 第一版代码输出结果,居然连不上网运行结果梳理 第二版结果测试 第一版代码 医疗顾问AI系统 - 基于Qwen API 的智能医疗助手 最终目标:构建一个能够查询疾病治疗方…...
硬件工程师笔试面试高频考点汇总——(2025版)
目录 1 电子器件部分 1.1 电阻 1.1.1 电阻选型时一般从哪几个方面进行考虑? 1.1.2 上拉下拉电阻的作用 1.1.3 PTC热敏电阻作为电源电路保险丝的工作原理 1.1.4 如果阻抗不匹配,有哪些后果 1.1.5 电阻、电容和电感0402、0603和0805封装的含义 1.1.6 电阻、电…...
春秋云镜【CVE-2017-18349】fastjson wp
知识点 fastjson反序列化 将json转为java对象的过程 漏洞存在版本 Fastjson<1.2.24 漏洞原理 fastjson引入的autotype功能,本来是为了区分同名同元素但是不同类型的对象序列化后内容一致无法还原的问题,但是这一操作允许了json数据中通过type来指定对…...
网络编程:八股文
一.Reactor网络模型 ------------------- | 应用主线程 | -------------------|v ------------------- | Reactor | | (事件分发器) | -------------------|v ------------------- | 事件多路分发器 | <--- epoll/poll/select -----------------…...
设计模式精讲 Day 11:享元模式(Flyweight Pattern)
【设计模式精讲 Day 11】享元模式(Flyweight Pattern) 文章内容 在软件开发过程中,我们常常需要处理大量相似对象的创建和管理问题。如果这些对象之间存在大量的重复信息,直接创建每一个对象会导致内存占用过高、系统性能下降。享…...
常用终端命令(Linux/macOS/bash 通用)分类速查表
文件与目录操作 命令作用说明pwd显示当前路径ls列出当前目录内容ls -l以列表形式显示文件详细信息ls -a显示所有文件(包括隐藏文件)cd <目录名>进入指定目录cd ..返回上一级目录cd ~回到用户主目录mkdir <目录名>创建目录mkdir -p a/b/c创建…...
Robyn高性能Web框架系列04:事件、中间件与错误处理
请求-响应过程 应用启动、关闭事件1、启动事件(Startup Events)2、关闭事件(Shutdown Events) 中间件1、前置中间件(BeforeRequest)2、后置中间件(AfterRequest)3、示例:…...
深入理解JavaScript设计模式之迭代器模式
文章目录 深入理解JavaScript设计模式之迭代器模式定义官方翻译白话翻译 实现jQuery中的each迭代器实现数组迭代器迭代器实现创建Dom元素 内部迭代器和外部迭代器内部迭代器外部迭代器 迭代类数组对象和字面量对象倒序迭代器中止迭代器迭代器的应用举例音乐播放器案例待输出更新…...
【项目管理】项目管理资料文档模板(ZIP,PPT,WORD)
项目交付文档 01项目详细调研计划编写规范V1.0.doc 03项目详细调研报告编写规范V1.0.doc 07软件需求规格说明书评审规范V1.0.doc 10.软件需求规格说明.doc 产品检查单,xls 工程评审.zip 软件标准过程集.zip 系统测试管理规程.docx 四)项目管理计划.doc 项目管理系统实施项目管理…...
DeepSeek中的提示库及其用法示例
《DEEPSEEK原生应用与智能体开发实践 图书》【摘要 书评 试读】- 京东图书 为了深入探索DeepSeek提示词样例的丰富内涵,充分挖掘其背后潜藏的无限可能,同时致力于为用户打造更为卓越、便捷且高效的使用体验,DeepSeek官网的API文档匠心独运地…...
292. Nim 游戏
292. Nim 游戏 - 力扣(LeetCode) 想法 枚举问题: n 1 ~ 3 ,由于我先手,我可以直接拿走全部的石头,所以我赢n 4,由于我先手,我拿掉 1 - 3 块石头 ,剩下的可能就是 1 -…...
STM32 串口通信②:蓝牙模块HC-05控制单片机
一 前言 上一篇我们已经成功实现单片机和电脑的连接,接下来,我们学习一个有趣的板块,HC-05蓝牙模块,这个蓝牙模块,我们就要建立手机和单片机的通讯啦,还是比较有趣的一个过程,大家可以跟着多操作…...
艾立泰数字化重塑汽车零部件包装租赁行业
在汽车零部件包装租赁行业,资产利用率低、流转效率差、运输成本高等痛点长期困扰企业。艾立泰科技通过数字化解决方案,成为该行业降本增效的关键合作伙伴,助力企业实现从传统管理模式向智能化的跃迁。 精准库存管理:告别“盲人摸…...
Windows电脑数据恢复终极指南:从原理到实战
Windows电脑数据恢复终极指南:从原理到实战 数据丢失是每个电脑用户都可能遭遇的噩梦。本文将为您全面解析Windows平台下的数据恢复技术,从基础原理到高级技巧,帮助您在文件误删、格式化、系统崩溃等情况下找回宝贵数据。 一、数据恢复基础…...
进入python虚拟环境的方法
首先,切换到虚拟环境所在的目录(即包含venv文件夹的目录): Cmd cd D:\phd\phd1spring\July\pythonstduy\projecton 然后,激活虚拟环境: Cmd .\venv\Scripts\activate 如果上述方法不行,还可…...
大数据时代UI前端的变革:从静态展示到动态交互
hello宝子们...我们是艾斯视觉擅长ui设计、前端开发、数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在大数据时代,信息以前所未有的速度和规模增长。这种数据环境的变化,深…...
海拔案例分享-门店业绩管理小程序
在各大电商平台和直播带货如火如荼来的当下,各行各业的门店都在积极寻求创新的管理方式,以提升业绩、优化运营。长沙的一家策划运营公司,敏锐地捕捉到这一市场需求,他们见过太多门店老板对着Excel表格叹气:美容店算错提…...
Python中的数据可视化:使用Matplotlib绘制图表
数据可视化是将复杂数据集转换为图形或图像表示的过程,旨在简化信息的解释和传达。Python作为一种多功能编程语言,提供了多种强大的库来实现这一目标,其中最受欢迎和广泛使用的是Matplotlib。 首先,我们需要确保已经安装了必要的…...
【VUE】1.准备工作
一、环境准备(本机仅需一次) 安装 Node.js(推荐 LTS 版本,包含 npm) 打开 VSCode,安装插件(推荐): Vetur 或 Volar(用于 Vue 支持) ESLint / Pr…...
Linux下的版本控制器Git(15)
文章目录 如何理解版本控制(9-0.00.00)Git 的理解Git 的历史具体操作和用法补充细节 简介:那个对Git的理解,是我用自己的话语结合故事进行阐述,可能理解的不到位,有些错误还请多多包含!说句实话…...
UI设计 | 审美积累 | 极繁风格(Maximalism / Complex UI)
如果极简追求“只保留必须的”,那极繁的设计思路就是“有条理地堆叠信息和情绪”。它不是无序的炫技,而是在秩序中有意识地填满视觉空间:字体层叠、图文混排、大量干扰信息并置,却又彼此克制。最终目标,是让用户在强信…...
MocapApi 中文文档 和github下载地址 NeuronDataReader(以下简称 NDR)的下一代编程接口
以下是 MocapApi 技术文档 github https://github.com/pnmocap/MocapApi?tabreadme-ov-file 国内可以查找getcode 英文文档 https://mocap-api.noitom.com/mocap_api_en.html 概述 MocapApi 是 NeuronDataReader(以下简称 NDR)的下一代编程接口&…...
c++面试题每日一学记录-C++类型转换
一、C++ 类型转换体系 C++ 提供 4 种命名转换操作符,比 C 风格转换更安全、意图更明确: 转换类型关键字主要用途安全检查静态转换static_cast相关类型转换(数值、类层次上行/下行)编译期动态转换dynamic_cast多态类型的安全下行转换运行时常量转换const_cast添加/移除 con…...
Maven 多模块项目调试与问题排查总结
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
【C#】C#异步编程:异步延时 vs 阻塞延时深度对比
文章目录 前言一、阻塞延时:Thread.Sleep1、 实现方式2、 工作原理3、 缺点 二、异步延时:Task.Delay1、 实现方式2、 工作原理3、 优点 三、深度对比四、实际应用示例对比1、 阻塞延时在UI应用中的问题2、 异步延时在UI应用中的正确用法3、 带取消功能的…...
c#实现halcon的rle编码blob分析
效果展示 实现功能 connection膨胀腐蚀开运算闭运算特征计算 核心代码 using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Drawing; using System.Linq;namespace view3d {// 基础对象类,类似于 Halcon 的 HO…...
python基于微信小程序的广西文化传承系统
文章目录 具体实现截图本项目支持的技术路线源码获取详细视频演示:文章底部获取博主联系方式!!!!本系统开发思路进度安排及各阶段主要任务java类核心代码部分展示主要参考文献:源码获取/详细视频演示 ##项目…...
Apache Flink深度解析:现代流处理引擎
好的,我来帮您写一篇关于Flink技术的详细介绍博客: Apache Flink深度解析:现代流处理引擎 一、Flink简介 Apache Flink是一个开源的分布式流处理和批处理统一计算引擎。它提供了数据流上的状态计算、精确一次性语义保证、高吞吐、低延迟等特性,能够运行在所有常见的集群…...
跨平台后端编程ASP.NET CORE Razor新一代Web开发框架C#
asp.net core Razor动态语言编程代替asp.net .aspx更高级吗? https://blog.csdn.net/xiaoyao961/article/details/148846065 C#Blazor应用-跨平台WEB开发VB.NET-CSDN博客 https://blog.csdn.net/xiaoyao961/article/details/148846437 Products.razor文件,Blazor和…...
【开源工具】一键解决使用代理后无法访问浏览器网页问题 - 基于PyQt5的智能代理开关工具开发全攻略
🌐【开源工具】一键解决使用代理后无法访问浏览器网页问题 - 基于PyQt5的智能代理开关工具开发全攻略 🌈 个人主页:创客白泽 - CSDN博客 🔥 系列专栏:🐍《Python开源项目实战》 💡 热爱不止于代…...
uniapp安卓GPIO电平控制
模块简介 本模块为 UniApp 提供了对 Android 系统下 GPIO 的访问能力,支持导出、设置方向、读写电平值等操作。适用于 Android 架构设备(如 RK3288 平台)。 支持功能 功能方法名说明初始化 GPIO 方向initGpio({gpio, direction})设置 GPIO…...
苹果芯片macOS安装版Homebrew(亲测)
在Linux服务器上安装一个软件常用yum,apt、dnf命令,同样macOS可以使用brew命令来安装软件。 brew会自动帮你下载、解压、安装和配置,更重要的是:它还会自动处理好软件之间的依赖关系,它将所有软件都安装在独立的统一目…...
vue | vue-macros 插件升级以及配置
Vue Macros 是一个为 Vue.js 提供更多宏和语法糖的开源项目vue-macros/vue-macros: Explore and extend more macros and syntax sugar to Vue. 问题:npm run build-only 打包时,报错:[Vue] Load plugin failed: vue-macros/volar 排查发现…...
计算机网络:(六)超详细讲解数据链路层 (附带图谱表格更好对比理解)
计算机网络:(六)超详细讲解数据链路层 前言一、数据链路层1. 数据链路层是什么?2. 哪些设备需要数据链路层?3. 数据链路层如何工作?4. 数据链路层的俩种信道4.1 点对点信道:一对一4.2 广播信道&…...
智能生成分析报告系统在危化安全生产监测预警评估中的应用
一、引言 在危险化学品安全生产监管中,传统的分析报告依赖人工整理与审核,效率低、响应慢,且极易受到主观判断、格式不规范、不同地区掌握尺度不一致的影响。而随着工业互联网、大数据、人工智能(AI)特别是大语言模型…...
微算法科技(NASDAQ:MLGO)研发可信共识算法TCA,解决区块链微服务中的数据一致性与安全挑战
随着区块链技术的不断演进和应用场景的拓展,微服务架构因其灵活性、可扩展性以及易于维护的特点,逐渐成为了构建复杂系统的首选架构模式。如何在微服务架构中有效应用区块链技术,确保数据的一致性和安全性,成为了一个亟待解决的问…...
UE5 开发遇到的bug整理
文章目录 一、人物在挂载某个Actor之后,移动有问题,可能是Actor类的碰撞没有关闭,和人物自身发生了碰撞。 一、人物在挂载某个Actor之后,移动有问题,可能是Actor类的碰撞没有关闭,和人物自身发生了碰撞。...
单片机——浮点数转换4位数码管显示
浮点数转换4位数码管显示 static char buffer[5]; int DecimalPlace 0; #define HideChar h void DisplayFloatOn4LED(float value) {long integer roundf(value );if (integer > 9999) //4位{integer 9999;snprintf(buffer, sizeof(buffer), "%4ld", integer…...
广东省专升本英语形容词与副词全梳理
一、形容词核心知识详解 (一)形容词的构成方式(附记忆技巧) 1. 后缀派生法(9 大核心后缀) ① -ly 结尾形容词(易混副词,重点记忆) ✅ 特点:虽以 - ly 结尾…...
GeoServer和GeoTools XML外部实体注入漏洞(CVE-2025-30220)
免责声明 本文档所述漏洞详情及复现方法仅限用于合法授权的安全研究和学术教育用途。任何个人或组织不得利用本文内容从事未经许可的渗透测试、网络攻击或其他违法行为。使用者应确保其行为符合相关法律法规,并取得目标系统的明确授权。 对于因不当使用本文信息而造成的任何直…...
Python Django全功能框架开发秘籍
本文在创作过程中借助 AI 工具辅助资料整理与内容优化。图片来源网络。 文章目录 引言一、Django 简介1.1 Django 的诞生与背景1.2 Django 的特点概述 二、Django 的核心特性2.1 ORM 特性2.1.1 ORM 原理与优势2.1.2 ORM 在实际应用中的优势 2.2 模板引擎2.2.1 模板引擎的工作机…...
四核 A53+工业级存储:移远 SC200L 与 pSLC SD NAND 如何重构 T-BOX 性能边界?
博客目录 一、移远 SC200L:T-BOX 的 “智慧大脑”二、米客方德 MKDN064GIL-ZA T-BOX:数据安全的坚固堡垒三、深度协同:拓展 T-BOX 应用边界 在车联网浪潮席卷而来的当下,T-BOX 作为汽车与外界交互的核心枢纽,其性能优劣…...
docker方式启动Jenkins
docker方式启动Jenkins 1.启动命令 我已经打包好了文件,如下命令即可启动 docker run -d -v jenkins_home:/var/jenkins_home -p 8088:8080 -p 50000:50000 --restarton-failure registry.cn-hangzhou.aliyuncs.com/devops_de/jenkins:lts-jdk17 还需要设置一下目录权限,要…...
【目标检测】图像处理基础:像素、分辨率与图像格式解析
🧑 博主简介:曾任某智慧城市类企业算法总监,目前在美国市场的物流公司从事高级算法工程师一职,深耕人工智能领域,精通python数据挖掘、可视化、机器学习等,发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…...
国产免费的k8s管理平台
xkube是一款永久免费且无任何功能限制的k8s集群管理平台,提供PC端和移动端全平台支持,具备完善的集群管理、运维监控和CI/CD发布功能,让企业轻松实现跨集群的统一管理和自动化运维。 技术特点: 1、xkube是一款国产永久免费的k8s…...
火山引擎大模型未来发展趋势
用户可能正在做技术选型或者行业研究,需要预测火山引擎在激烈竞争中的突围方向。从问题简洁性看,ta可能已经有一定基础认知,不需要我从零科普大模型概念。 火山引擎作为字节跳动的技术输出平台,优势在于背靠抖音、今日头条等超级应…...