当前位置: 首页 > news >正文

Qt网络编程-TCP与UDP

网络基础

TCP与UDP基础

关于TCP与UDP的基础这里就不过多介绍了,具体可以查看对应百度百科介绍:

TCP(传输控制协议)_百度百科 (baidu.com)

UDP_百度百科 (baidu.com)

需要知道这两者的区别:

  1. 可靠性:

    • TCP:TCP 是一种面向连接的协议,它提供可靠的数据传输。它使用序号、确认和重传等机制来确保数据的可靠性,以及按序传递数据包。如果数据包丢失或损坏,TCP 会自动进行重传,直到数据被正确接收。
    • UDP:UDP 是一种无连接的协议,它不提供数据包的可靠性保证。UDP 发送的数据包可能丢失、重复或无序,因此它不适合对数据可靠性要求很高的应用。
  2. 连接性:

    • TCP:TCP 是面向连接的,它在通信双方建立连接后(有客户端与服务器之分)才能进行数据传输。TCP 连接是可靠的、有序的、全双工的,通信双方可以进行双向通信。
    • UDP:UDP 是无连接的,它不需要在通信双方之间建立连接(没有客户端与服务器之分)。每个 UDP 数据包都是独立的,发送者和接收者之间没有持久的连接。
  3. 效率:

    • TCP:TCP 通过使用流量控制和拥塞控制等机制,以及连接的建立和维护,会产生一定的开销。因此,TCP 在可靠性和有序性方面提供了较高的保证,但可能会牺牲一些效率。
    • UDP:UDP 不需要进行连接的建立和维护,也不需要进行重传或流量控制等操作,因此它通常比 TCP 具有更低的开销和更高的效率。

网络通信以上两者都绕不开IP地址与端口这两个。

开发调试所需工具

一般情况需要网络调试助手或者wireshark抓包工具,网络调试助手我用的是NetAssist。关于NetAssist和WireShark怎么使用,后面会介绍。

windows与linux如何查看和修改本地的IP端口

Window

cmd命令行:ipconfig/all

修改:

设置选中“网络和Internet”

Linux

命令行:ifconfig -a:

static QStringList getIPAddresses() {QStringList addresses;for (const QHostAddress &address : QNetworkInterface::allAddresses()) {if (address.protocol() == QAbstractSocket::IPv4Protocol)addresses.append(address.toString());}return addresses;
}

或者直接查看网络设置。

使用Qt函数获取

Qt要使用网络模块记得工程文件添加:QT += network

static QStringList getIPAddresses() {QStringList addresses;for (const QHostAddress &address : QNetworkInterface::allAddresses()) {if (address.protocol() == QAbstractSocket::IPv4Protocol)addresses.append(address.toString());}return addresses;
}

编译运行查看打印:

Windows与Linux查看本地连接情况

Windows和Linux都需要借助netstat命令,但是两者稍微有一些不一样。

Windows

比如我使用刚刚的调试助手NetAssist,建立一个tcp服务器,然后监听IP:192.168.5.1,端口:8080。

查看一下这个服务器是否监听成功,命令行输入:netstat -antp TCP(‘p’指定对应协议,后面需要接协议类型TCP或UDP)

 或者直接输入命令 netstat -antp TCP|findstr 8080:

再起一个调试助手以客户端的形式连接这个服务器:

 再次输入: netstat -antp TCP|findstr 8080:

能够查看到刚刚建立的连接。

查看对应链接是哪个应用建立的,先输入: netstat -antpo TCP|findstr 8080:

然后使用tasklist查看对应进程: 

如果是UDP改为 netstat -antp UDP|findstr 8080 即可

Linux 

Linux 的netstat的命令指定对应协议不需要 -p TCP或者-p UDP,而是-t就是TCP,-u就是UDP,如下图所示:

 Qt实现TCP

因为TCP是需要建立链接,分客户端和服务器端的,所以需要分别编写。

服务器端

服务器由QTcpServer来实现,QTcpServer的信号:

需要注意newConnection这个信号,当有客户端连接这个服务器时,会触发这个信号。

所有的方法:


需要注意的几个方法:


bool  listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0)
 
监听对应IP和端口,IP为空则默认监听any

close()

停止监听

bool isListening() const
 
是否正在监听

QHostAddress serverAddress() const
 
监听的IP地址

quint16 serverPort() const
 
监听的端口

void setMaxPendingConnections(int numConnections)
 
设置允许建立的最大连接数

比如监听IP 127.0.0.1 端口 8080:

QTcpServer server;

server.listen(QHostAddress("127.0.0.1"),8080); 

写一个简单的例子。

ui:

头文件:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{Q_OBJECT
public:MainWindow(QWidget *parent = nullptr);~MainWindow();
private slots:void on_listen_clicked();void on_disconnect_clicked();void on_send_clicked();void newConnection();
private:Ui::MainWindow *ui;QTcpServer *m_Server;QTcpServer *m_Server1;QList<QTcpSocket *> m_Sockets;void showLog(const QString &log);
};
#endif // MAINWINDOW_H

 源文件:

#include "mainwindow.h"
#include <QDateTime>
#include <QHostAddress>
#include <QNetworkInterface>
#include "ui_mainwindow.h"
static QStringList getIPAddresses() {QStringList addresses;for (const QHostAddress &address : QNetworkInterface::allAddresses()) {if (address.protocol() == QAbstractSocket::IPv4Protocol)addresses.append(address.toString());}return addresses;
}MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);setWindowTitle("TcpServer");ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);ui->localIp->addItems(getIPAddresses());ui->tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);m_Server = new QTcpServer;connect(m_Server, &QTcpServer::newConnection, this,&MainWindow::newConnection);for (QTcpSocket *socket : m_Sockets) {connect(socket, &QTcpSocket::readyRead, [=]() {showLog(QString("%1:%2:%3").arg(socket->peerAddress().toString()).arg(socket->peerPort()).arg(QString(socket->readAll().toHex())));});connect(socket, &QTcpSocket::disconnected, [=]() {showLog(QString("disconnect:%1:%2:%3").arg(socket->peerAddress().toString()).arg(socket->peerPort()).arg(QString(socket->readAll().toHex())));for (int i = 0; i < ui->tableWidget->rowCount(); i++) {QTableWidgetItem *ipItem = ui->tableWidget->item(i, 0);QTableWidgetItem *portItem = ui->tableWidget->item(i, 1);if (nullptr != ipItem && nullptr != portItem) {if (ipItem->text() == socket->peerAddress().toString() &&portItem->text() == socket->peerPort()) {ui->tableWidget->removeRow(i);break;}}}});connect(socket,static_cast<void (QTcpSocket::*)(const QAbstractSocket::SocketError)>(&QTcpSocket::error),[=](QAbstractSocket::SocketError error) {qDebug() << "error:" << error;showLog("error:" + QString::number(int(error)));});connect(socket, &QTcpSocket::stateChanged,[=](QAbstractSocket::SocketState state) {qDebug() << "stateChanged:" << state;showLog("stateChanged:" + QString::number(int(state)));});}
}MainWindow::~MainWindow() { delete ui; }void MainWindow::on_listen_clicked() {if (ui->listen->text() == "listen") {if (m_Server->listen(QHostAddress(ui->localIp->currentText()),ui->localPort->value()))ui->listen->setText("listening");elseui->textEdit->append("listen fail");} else {for (QTcpSocket *socket : m_Sockets) {socket->close();socket->disconnectFromHost();}m_Server->close();ui->listen->setText("listen");}
}void MainWindow::on_disconnect_clicked() {int row = ui->tableWidget->currentRow();if (-1 != row) {QTableWidgetItem *ipItem = ui->tableWidget->item(row, 0);QTableWidgetItem *portItem = ui->tableWidget->item(row, 1);if (nullptr != ipItem && nullptr != portItem) {QString ip = ipItem->text();quint16 port = portItem->text().toUShort();for (QTcpSocket *socket : m_Sockets) {if (ip == socket->peerAddress().toString() &&port == socket->peerPort()) {socket->close();socket->disconnectFromHost();break;}}}}
}void MainWindow::on_send_clicked() {QByteArray ba = ui->send->text().toUtf8();int row = ui->tableWidget->currentRow();if (-1 != row) {QTableWidgetItem *ipItem = ui->tableWidget->item(row, 0);QTableWidgetItem *portItem = ui->tableWidget->item(row, 1);if (nullptr != ipItem && nullptr != portItem) {QString ip = ipItem->text();quint16 port = portItem->text().toUShort();for (QTcpSocket *socket : m_Sockets) {if (ip == socket->peerAddress().toString() &&port == socket->peerPort()) {socket->write(ba);break;}}}}
}void MainWindow::newConnection() {QTcpSocket *socket = m_Server->nextPendingConnection();m_Sockets.append(socket);// m_TcpSocket = socket;int row = ui->tableWidget->rowCount();ui->tableWidget->insertRow(row);QTableWidgetItem *ipItem =new QTableWidgetItem(socket->peerAddress().toString());QTableWidgetItem *portItem =new QTableWidgetItem(QString::number(socket->peerPort()));qDebug() << socket->peerAddress().toString() << "," << socket->peerPort()<< "," << socket->peerName();ui->tableWidget->setItem(row, 0, ipItem);ui->tableWidget->setItem(row, 1, portItem);connect(socket, &QTcpSocket::disconnected, [=]() {showLog(QString("disconnected:%1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()));// m_TcpSocket = nullptr;for (int i = 0; i < ui->tableWidget->rowCount(); i++) {QTableWidgetItem *ipItem = ui->tableWidget->item(i, 0);QTableWidgetItem *portItem = ui->tableWidget->item(i, 1);if (nullptr != ipItem && nullptr != portItem) {if (ipItem->text() == socket->peerAddress().toString() &&portItem->text() == QString::number(socket->peerPort())) {ui->tableWidget->removeRow(i);break;}}}});
}void MainWindow::showLog(const QString &log) {ui->textEdit->append(QString("%1:%2").arg(QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss.zzz")).arg(log));
}

有客户端连接后,会触发newConnection这个信号,然后在槽函数中使用nextPendingConnection()这个方法获取对应的客户端QTcpSocket 指针对象。客户端发送消息后会触发readyRead这个信号,使用QTcpSocket的readAll获取发送的信息。编译运行,输入监听的ip和端口然后点击listen按钮然后使用命令查看是否开始监听对应ip和端口:

然后使用调试助手作为客户端连接这个服务器:

 

可以看到触发了newConnection信号,然后获取对应客户端对象将其信息显示到了的表格上面。

实验链接的建立与取消以及消息的互相发送:

可以实现对应的通讯。 

以上是使用调试助手,也可以使用WireShark抓包查看发送和接受的数据。需要注意的是如果客户端和服务器都在本地自己发自己收是用WireShark抓不到的。

这里简单说一下wireshark的用法,首先选择需要抓取的网卡:

比如ping就是走的tcp,测试时我是用 虚拟机ping我的主机,如何使vmware虚拟机和主机ping通可以参考这位博主的博客:实现虚拟机(VM15.5.0)与本机相互通信_vmware和主机怎样才能ping通-CSDN博客

然后查看wireshark可以看到ping的报文:

因为我的主机ip192.168.1.3,虚拟机ip是192.168.1.4,可以输入“ip.src==192.168.1.4 && ip.dst==192.168.1.3” 来过滤:

 同样,我使用虚拟机和主机建立tcp连接然后发送消息也是可以抓到:

 

 

X

客户端

客户端由QTcpSocket实现,QTcpSocket继承自QAbstractSocket,比如上文中在虚拟机中建立一个tcp服务器,监听ip192.168.1.3,端口12345:

QTcpSocket *socket =new QTcpSocket;
socket->connectToHost(QHostAddress(),12345);
if(socket->waitForConnected())
{//TODO 连接成功
}
else
{//TODO 连接失败
}connect(socket,&QTcpSocket::disconnected,[=](){
//TODO 处理连接断开
});
connect(socket, &QTcpSocket::readyRead, [=]() {QByteArray receiveData=socket->readAll();//TODO 处理接收的数据});QByteArray sendData;
//TODO 处理发送数据
//发送数据
socket->write(sendData);
//断开连接,两种方式
socket->abort;//强制中断连接
socket->disconnectFromHost();//不会马上关闭连接,等待资源释放后才会中断连接

另外客户端套接字可以绑定bind对应ip和端口,如果没有绑定,则系统会使用之绑定一个随即的可用的ip和端口 :

Qt实现UDP

因为UDP不用建立连接,不用分服务器和客户端,所以对应Qt的UDP部分,只需要使用QUdpSocket一个即可:

QUdpSocket同QTcpSocket一样都继承自QAbstractSocket,使用UDP通信前,对应udp套接字需要绑定对应ip与端口,然后发送数据时需要知道对方的ip与端口(UDP分单播、组播与广播,这里只说单播,组播与广播后面博客再写):

QUdpSocket *udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress("192.168.1.3"), 12345);
connect(udpSocket, &QUdpSocket::readyRead,[=](){while (udpSocket->hasPendingDatagrams()) {QByteArray data;QHostAddress host;quint16 port;data.resize(udpSocket->pendingDatagramSize());udpSocket->readDatagram(data.data(), data.size(), &host, &port);//TODO 处理接受数据}
});
QByteArray sendData;
//TODO 处理发送数据
udpSocket->writeDatagram(sendData, QHostAddress("192.168.1.4"),12345);
//取消绑定
udpSocket->unbind();

使用网络助手模拟udp通信:

使用自己写的udp程序在虚拟机中与之通信:

 使用wireshark抓包:

 

相关文章:

Qt网络编程-TCP与UDP

网络基础 TCP与UDP基础 关于TCP与UDP的基础这里就不过多介绍了&#xff0c;具体可以查看对应百度百科介绍&#xff1a; TCP&#xff08;传输控制协议&#xff09;_百度百科 (baidu.com) UDP_百度百科 (baidu.com) 需要知道这两者的区别&#xff1a; 可靠性&#xff1a; TC…...

Promise 常见题目

微信搜索“好朋友乐平”关注公众号。 1. Promise 对象池 请你编写一个异步函数 promisePool &#xff0c;它接收一个异步函数数组 functions 和 池限制 n。它应该返回一个 promise 对象&#xff0c;当所有输入函数都执行完毕后&#xff0c;promise 对象就执行完毕。 池限制 定…...

五大架构风格之五:仓库架构风格

仓库架构风格&#xff1a; 仓库风格架构&#xff08;Repository Architecture Style&#xff09;是一种软件架构模式&#xff0c;它主要用于处理系统中的持久化数据存储和检索。在这一风格中&#xff0c;仓库&#xff08;Repository&#xff09;作为应用程序与数据库或其他持久…...

探索设计模式的魅力:外观模式简化术-隐藏复杂性,提供简洁接口的设计秘密

设计模式专栏&#xff1a;http://t.csdnimg.cn/U54zu 目录 引言&#xff1a;探索简化之路 一、起源和演变 二、场景案例分析 2.1 不用模式实现&#xff1a;用一坨坨代码实现 2.2 问题 2.3 外观模式重构代码 定义 界面 接口 利用外观模式解决问题步骤 外观模式结构和说明 重构…...

java之Maven

1. maven Maven是管理和构建java项目的工具 项目依赖资源(jar包)的管理,避免版本冲突统一项目结构项目构建&#xff0c;标准跨平台(Linux,window,MacOS)的自动化项目管理 2.maven依赖仓库 2.maven安装 maven安装视频教程 3. IDEA集成Maven 4. maven的依赖范围 5. maven生命…...

Elasticsearch(四)

是这样的前面的几篇笔记&#xff0c;感觉对我没有形成知识体系&#xff0c;感觉乱糟糟的&#xff0c;只是大概的了解了一些基础知识&#xff0c;仅此而已&#xff0c;而且对于这技术栈的学习也是为了在后面的java开发使用&#xff0c;但是这里的API学的感觉有点乱&#xff01;然…...

蓝桥杯-X图形

问题描述 给定一个字母矩阵。一个 X 图形由中心点和由中心点向四个 45度斜线方向引出的直线段组成&#xff0c;四条线段的长度相同&#xff0c;而且四条线段上的字母和中心点的字母相同。 一个 X 图形可以使用三个整数 r,c,L 来描述&#xff0c;其中 r,c 表示中心点位于第 r 行…...

2. Maven 继承与聚合

目录 2. 2.1 继承 2.2继承关系 2.2.1 思路分析 2.2.2 实现 2.1.2 版本锁定 2.1.2.1 场景 2.1.2.2 介绍 2.1.2.3 实现 2.1.2.4 属性配置 2.2 聚合 2.2.1 介绍 2.2.2 实现 2.3 继承与聚合对比 maven1&#xff1a;分模块设计开发 2. 在项目分模块开发之后啊&#x…...

如何把手机平板变为电脑的屏幕

文章目录 安装软件运行效果结尾 本文首发地址 https://h89.cn/archives/181.html 最新更新地址 https://gitee.com/chenjim/chenjimblog 闲置的手机平板、触屏音箱等&#xff0c;均可作为电脑的扩展屏&#xff0c;为电脑增加一块显示屏&#xff0c;本文介绍如何使用免费的软件s…...

Amazon Dynamo学习总结

目录 一、Amazon Dynamo的问世 二、Amazon Dynamo主要技术概要 三、数据划分算法 四、数据复制 五、版本控制 六、故障处理 七、成员和故障检测 一、Amazon Dynamo的问世 Amazon Dynamo是由亚马逊在2007年开发的一种高度可扩展和分布式的键值存储系统&#xff0c;旨在解…...

appium抓包总结

appium抓包总结 背景&#xff1a;有些app通过抓包工具charles等抓不到接口数据&#xff0c;应为这一类抓包工具只能抓到应用层的数据包&#xff0c;而某些app的接口是走的传输层协议&#xff0c;所以此时只能通过AppIUM工具来进行抓包。 1、Appium 是什么&#xff1f; Appium…...

arcgis各种版本下载

arcgic 下载&#xff01;&#xff01;&#xff01; ArcGIS是一款地理信息系统软件&#xff0c;由美国Esri公司开发。它提供了一系列完整的GIS功能&#xff0c;包括地图制作、空间数据管理、空间分析、空间信息整合、发布与共享等。ArcGIS是一个可扩展的GIS平台&#xff0c;提供…...

第五篇:MySQL常见数据类型

MySQL中的数据类型有很多&#xff0c;主要分为三类:数值类型、字符串类型、日期时间类型 三个表格都在此网盘中&#xff0c;需要者可移步自取&#xff0c;如果觉得有帮助希望点个赞~ MySQL常见数据类型表 数值类型 &#xff08;注&#xff1a;decimal类型举例&#xff0c;如1…...

Oracle用BETWEEN AND查某年的数据可能会丢失条数

随便找一张有日期&#xff08;字段类型为DATE&#xff09;的表即可测试。 假设存在这样一张表HOLIDAY&#xff0c;里面存储的是某些国家(表字段为COUNTRY_CODE)某些年的法定假日日期(表字段为HOLIDAY_DATE)。 我想查中国在2023年和2024年的法定假日日期。 BETWEEN AND 首先想…...

Nuscenes数据集点云数据如何转换到图像上

零、概要 注意&#xff1a;该文章是手写ai自动驾驶&#xff0c;Nuscenes数据集的笔记。 首先&#xff0c;学习需要使用到 nuScenes 数据集。python 工具需要使用到 nuscenes-devkit、pyquaternion from nuscenes.nuscenes import NuScenes from pyquaternion import Quatern…...

【C语言期末】商品管理系统

本文资源&#xff1a;https://download.csdn.net/download/weixin_47040861/88820155 1.题目要求 商品管理系统 商品信息包括&#xff1a;包括编号、类别、名称、价格、折扣比例、生产时间 、存货数量等要求&#xff1a;1、信息首先保存在文件中&#xff0c;然后打开文件进行…...

单片机学习笔记---串口通信(2)

目录 串口内部结构 串口相关寄存器 串口控制寄存器SCON SM0和SM1 SM2 REN TB8和RB8 TI和RI 电源控制寄存器PCON SMOD 串口工作方式 方式0 方式0输出&#xff1a; 方式0输入 方式1 方式1输出。 方式1输入 方式2和方式3 方式2和方式3输出&#xff1a; 方式2和…...

【Java】乐观锁有哪些常见实现方式?

Java中的乐观锁主要有两种常见的实现方式&#xff1a; CAS&#xff08;Compare and Swap&#xff09;&#xff1a;这是实现乐观锁的核心算法。CAS操作包含三个参数&#xff1a;内存地址V、旧的预期值A和要修改的新值B。执行CAS操作时&#xff0c;会先比较内存地址V中的值是否等…...

Javaweb之SpringBootWeb案例之登录校验功能的详细解析

2. 登录校验 2.1 问题分析 我们已经完成了基础登录功能的开发与测试&#xff0c;在我们登录成功后就可以进入到后台管理系统中进行数据的操作。 但是当我们在浏览器中新的页面上输入地址&#xff1a;http://localhost:9528/#/system/dept&#xff0c;发现没有登录仍然可以进…...

CSS之盒模型

盒模型概念 浏览器盒模型&#xff08;Box Model&#xff09;是CSS中的基本概念&#xff0c;它描述了元素在布局过程中如何占据空间。盒模型由内容&#xff08;content&#xff09;、内边距&#xff08;padding&#xff09;、边框&#xff08;border&#xff09;、和外边距&…...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

代码规范和架构【立芯理论一】(2025.06.08)

1、代码规范的目标 代码简洁精炼、美观&#xff0c;可持续性好高效率高复用&#xff0c;可移植性好高内聚&#xff0c;低耦合没有冗余规范性&#xff0c;代码有规可循&#xff0c;可以看出自己当时的思考过程特殊排版&#xff0c;特殊语法&#xff0c;特殊指令&#xff0c;必须…...

解析“道作为序位生成器”的核心原理

解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制&#xff0c;重点解析"道作为序位生成器"的核心原理与实现框架&#xff1a; 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...