网易首页 > 网易号 > 正文 申请入驻

UDS诊断协议深度解析:从理论到C++实战

0
分享至


1. 引言

在当代汽车电子与嵌入式系统中,UDS(Unified Diagnostic Services,统一诊断服务)已成为 ECU(电子控制单元)诊断、软件刷写、生产线终端测试及售后维护的核心协议。它基于 ISO 14229 标准,定义了一套与传输层无关的、面向应用的诊断消息格式与服务流程。无论是传统燃油车还是新能源车,UDS 都是 OBD(车载诊断)之上的“高阶语言”,也是嵌入式软件工程师面试中的高频考点。

本文将从协议分层、服务类型、帧结构、关键流程(安全访问、DTC、会话管理)到底层传输层 CAN-TP(ISO 15765-2),进行系统性的专业讲解,并辅以可落地的 C++ 代码示例,帮助读者将抽象规范转化为实际工程能力。

2. UDS 协议的层次结构

UDS 遵循 OSI 七层模型,但其核心定义在应用层(第 7 层),而具体物理/数据链路层则依赖底层总线(如 CAN、LIN、FlexRay、Ethernet)。常见组合如下:

OSI 层

协议/标准

作用

应用层

ISO 14229-1 (UDS)

定义诊断服务、子功能、数据格式

表示/会话层

通常合并到应用层或由传输层处理

传输层

ISO 15765-2 (CAN-TP)

分段/重组、流控(针对 CAN)

网络层

无(CAN 直接寻址)

数据链路层

ISO 11898-1/2 (CAN)

CAN 帧结构、仲裁、错误检测

物理层

ISO 11898-2/3

电气特性、速率


关键点:UDS 服务(如 0x10 诊断会话控制)作为 SID(Service Identifier)位于应用层报文首字节,而底层 CAN-TP 通过 PCI(Protocol Control Information)负责长报文的分包与流量控制,两者协同完成端到端诊断通信。
3. UDS 常用服务(SID)概览

UDS 定义了超过 30 种服务,按功能分组。面试中最常涉及的服务及其 SID:

SID(十六进制)

服务名称

简述

0x10

DiagnosticSessionControl

切换诊断会话(默认/编程/扩展),影响服务可用性

0x11

ECUReset

执行 ECU 软复位/硬复位

0x14

ClearDiagnosticInformation

清除 DTC(故障码)

0x19

ReadDTCInformation

读取 DTC 状态、快照、扩展数据等(子功能丰富)

0x22

ReadDataByIdentifier

按 DID(数据标识符)读取数据(如 VIN、软件版本)

0x27

SecurityAccess

安全访问(种子-密钥认证),保护敏感操作

0x2E

WriteDataByIdentifier

按 DID 写入数据(标定、配置)

0x34/36/37

RequestDownload / TransferData / RequestTransferExit

固件下载(Bootloader 刷写)

0x3E

TesterPresent

维持诊断会话活跃,防止超时回退默认会话

0x85

ControlDTCSetting

控制 DTC 记录开启/关闭(用于刷写期间避免误报)


4. UDS 帧类型与报文结构

UDS 使用请求/响应模型,每一帧都遵循固定的应用层格式。

4.1 请求帧(Request)

  • 无子功能:[SID] + [参数...]

  • 有子功能:[SID] + [SubFunction] + [参数...]

    • 子功能最高位(bit 7)常称为 **suppressPositiveResponse**,若为 1,则 ECU 不返回肯定响应(仅用于周期性查询以节省总线负载)。

4.2 肯定响应(Positive Response)
  • 无子功能:[(SID + 0x40)] + [响应数据]

  • 有子功能:[(SID + 0x40)] + [SubFunction] + [响应数据]

例如:0x10 0x02请求进入编程会话 → 肯定响应0x50 0x02。

4.3 否定响应(Negative Response)

固定格式:[0x7F] + [SID] + [NRC]
NRC(Negative Response Code)单字节,表明失败原因。

示例:0x7F 0x22 0x12表示读取 DID 服务因子功能不支持而失败。

5. 重要服务详解 5.1 安全访问(0x27)——种子密钥机制

安全访问用于保护刷写、标定改写等高危操作。流程如下:

  1. 请求种子:客户端发送0x27 0x01(奇数子功能,级别 1 请求种子)。ECU 返回0x67 0x01 [Seed_Bytes](通常 4~8 字节随机数),并启动超时定时器。

  2. 计算密钥:客户端使用预先约定的算法(如 AES、自定义异或+移位)对种子计算密钥。

  3. 发送密钥:客户端发送0x27 0x02 [Key_Bytes](偶数子功能,级别 1 发送密钥)。

  4. 验证:ECU 用相同算法计算期望密钥,比较。

  • 0x35(Invalid Key)

  • 0x36(Exceeded Number of Attempts)——尝试次数超限,进入锁定态

  • 0x37(Required Time Delay Not Expired)——需等待冷却时间

  • 成功:返回0x67 0x02,解锁对应级别,后续允许访问受保护服务。

  • 失败:返回否定响应,常见 NRC:

防暴力破解设计:连续错误超限后,ECU 需冷启动或等待超时才能再次尝试。

5.2 读取 DTC 信息(0x19)

0x19是诊断中最复杂的服务,拥有 28 个子功能。常用子功能:

子功能

名称

用途

0x01

reportNumberOfDTCByStatusMask

按状态掩码统计 DTC 数量

0x02

reportDTCByStatusMask

列出所有满足状态掩码的 DTC 及其状态字节

0x04

reportDTCSnapshotIdentification

读取某个 DTC 的快照记录标识符

0x06

reportDTCSnapshotDataByIdentifier

读取指定 DTC 的快照数据(冻结帧)

0x0A

reportSupportedDTC

列出 ECU 支持的所有 DTC(不关心状态)

DTC 状态字节(Status Byte)是 8 位掩码,每一位代表一种老化/状态维度:

Bit

名称

含义

0

testFailed

当前诊断测试失败(瞬态)

1

testFailedThisOperationCycle

本驾驶循环内曾失败

2

pendingDTC

本循环内发生但尚未确认(等待老化)

3

confirmedDTC

已确认(故障灯 MIL 亮起的依据)

4

testNotCompletedSinceLastClear

自上次清除后测试未完成

5

testFailedSinceLastClear

自上次清除后曾失败

6

testNotCompletedThisOperationCycle

本循环内测试未完成

7

warningIndicatorRequested

请求点亮警告灯(如 MIL)


5.3 会话控制(0x10)与 TesterPresent(0x3E)

  • 诊断会话:ECU 在不同会话下暴露不同的服务集。

    • 默认会话 (0x01):基础诊断,如读取 DTC、读数据。

    • 编程会话 (0x02):允许刷写,通常会禁止 DTC 记录并重置 ECU。

    • 扩展会话 (0x03):允许 I/O 控制、例程执行等高级测试。

  • 会话超时:若在TsessionTimeout(典型 5s)内无任何诊断请求,ECU 自动回退至默认会话,以保证安全性。
    因此,客户端需周期性发送0x3E 0x00(TesterPresent,子功能 0x00 表示无额外参数)来“保活”。ECU 肯定响应为0x7E 0x00。

5.4 物理寻址 vs 功能寻址
  • 物理寻址:CAN ID 唯一对应一个 ECU(如请求 0x7A1,响应 0x7A9),用于点对点操作(刷写、读取具体 ECU 信息)。

  • 功能寻址:CAN ID 广播给一组或全部 ECU(如 0x7DF),多个 ECU 可同时响应(通常要求抑制部分响应以防冲突)。常用于全局查询(如所有 ECU 的 DTC 状态)。

6. CAN-TP(ISO 15765-2)多帧传输机制

当 UDS 报文长度超过单帧 CAN 的有效载荷(CAN 数据场最多 8 字节,但 UDS 应用层占用 PCI 后通常最多 7 字节数据)时,必须借助CAN-TP进行分包和重组。

CAN-TP 定义了四种协议控制信息(PCI)帧类型,位于每个 CAN 帧的首字节(或前两字节):

PCI 类型

高四位 (Nibble)

描述

单帧 SF

0

短报文(总长 ≤ 7),低四位表示数据长度。例:03 22 F1 90

首帧 FF

1

多帧传输的第一帧,低四位 + 后续字节共 12 位表示总长度(≤4095)。例:10 1A 62 F1 90 ...表示总长 26 字节

连续帧 CF

2

后续数据帧,低四位为序列号(从 1 开始,模 16)。例:21 ...,22 ...

流控帧 FC

3

接收方发送,用于控制发送速率。包含 FlowStatus(0=继续,1=等待,2=溢出)、BlockSize、STmin

多帧通信流程:

  1. 发送方发送FF,携带总长度。

  2. 接收方收到 FF 后,回复FC,告知:

  • FlowStatus= 0(允许发送)

  • BlockSize(BS):发送方在收到下一个 FC 前可连续发送的 CF 数量(0 表示不限)

  • SeparationTime(STmin):两个 CF 间的最小间隔(单位 ms)

发送方根据 FC 参数发送CF,直到发送完总长度。

若 BS > 0,发送方每发送完一个 Block 的 CF 后,必须等待新的 FC 才能继续。

实现要点:接收方需维护重组缓冲区,按 SN 顺序拼接数据;发送方需具备定时器和状态机以处理 FC 和超时。
7. C++ 实战:设计与实现 UDS 协议栈核心模块

下面我们使用 C++ 设计一个轻量级 UDS 协议栈,包含:

  • UDS 消息解析与构造

  • CAN-TP 分包/组包器

  • 会话与安全访问状态机框架

7.1 UDS 消息基础类

#include  

#include
#include
#include

// UDS 消息结构(应用层)
struct UdsMessage {
uint8_t sid; // 服务标识符
uint8_t subFunc; // 子功能(若存在)
std::vector data; // 参数或响应数据
bool hasSubFunction; // 是否包含子功能
};

// 否定响应码枚举
enum class Nrc : uint8_t {
Positive = 0x00,
GeneralReject = 0x10,
ServiceNotSupported = 0x11,
SubFunctionNotSupported = 0x12,
InvalidMessageLength = 0x13,
ConditionsNotCorrect = 0x22,
RequestSequenceError = 0x24,
InvalidKey = 0x35,
ExceededNumberOfAttempts = 0x36,
RequiredTimeDelayNotExpired = 0x37,
// ... 其他 NRC
};

// 构造肯定响应(无子功能)
std::vector BuildPositiveResponse(uint8_t sid, const std::vector& respData) {
std::vector msg;
msg.push_back(sid + 0x40);
msg.insert(msg.end(), respData.begin(), respData.end());
return msg;
}

// 构造肯定响应(有子功能)
std::vector BuildPositiveResponseWithSub(uint8_t sid, uint8_t subFunc, const std::vector& respData) {
std::vector msg;
msg.push_back(sid + 0x40);
msg.push_back(subFunc);
msg.insert(msg.end(), respData.begin(), respData.end());
return msg;
}

// 构造否定响应
std::vector BuildNegativeResponse(uint8_t sid, Nrc nrc) {
return {0x7F, sid, static_cast(nrc)};
}
7.2 解析 UDS 请求(含子功能识别)

// 解析请求,返回 UdsMessage 对象,并检查合法性
bool ParseUdsRequest(const std::vector& raw, UdsMessage& outMsg) {
if (raw.empty()) return false;
outMsg.sid = raw[0];
outMsg.hasSubFunction = false;
outMsg.subFunc = 0;
outMsg.data.clear();


// 判断是否有子功能:通常根据 SID 定义,但简化判断:若长度 >=2 且第二字节 bit7 可能为子功能标志
// 真实实现需要查表,这里简单假设所有服务都可能有子功能(除 0x22 等少数)
if (raw.size() >= 2) {
// 有些服务固定无子功能,此处以实际定义为准(例如 0x22 无子功能)
if (outMsg.sid == 0x22 || outMsg.sid == 0x2E) {
// 无子功能,数据从第1字节开始
outMsg.data.assign(raw.begin() + 1, raw.end());
} else {
outMsg.hasSubFunction = true;
outMsg.subFunc = raw[1];
outMsg.data.assign(raw.begin() + 2, raw.end());
}
} else {
// 单字节请求(如 0x11 无子功能)
outMsg.data.clear();
}
return true;
}
7.3 安全访问(0x27)简易实现

class SecurityAccess {
public:
enum Level { Level1 = 1, Level2 = 2 };
SecurityAccess() : locked_(true), attemptCounter_(0), unlockLevel_(0) {}

// 处理请求种子 (subFunc 奇数)
std::vector HandleSeedRequest(uint8_t subFunc) {
if (locked_ && attemptCounter_ >= 3) {
// 锁定状态,返回 NRC ExceededNumberOfAttempts
return BuildNegativeResponse(0x27, Nrc::ExceededNumberOfAttempts);
}
// 生成种子(伪随机)
uint8_t seed[4] = {0xA1, 0xB2, 0xC3, 0xD4}; // 实际应从 RNG 获取
currentSeed_ = {seed[0], seed[1], seed[2], seed[3]};
// 返回肯定响应:67 + subFunc + seed
std::vector resp = {0x67, subFunc};
resp.insert(resp.end(), currentSeed_.begin(), currentSeed_.end());
return resp;
}

// 处理发送密钥 (subFunc 偶数)
std::vector HandleKeySend(uint8_t subFunc, const std::vector& key) {
if (locked_) {
return BuildNegativeResponse(0x27, Nrc::ExceededNumberOfAttempts);
}
// 计算期望密钥(采用简单异或示例)
std::vector expectedKey;
for (auto b : currentSeed_) expectedKey.push_back(b ^ 0x55);
// 比较
if (key == expectedKey) {
attemptCounter_ = 0;
unlockLevel_ = (subFunc >> 1); // 简单映射
locked_ = false;
return {0x67, subFunc}; // 肯定响应
} else {
attemptCounter_++;
if (attemptCounter_ >= 3) locked_ = true;
return BuildNegativeResponse(0x27, Nrc::InvalidKey);
}
}

bool IsUnlocked() const { return !locked_; }

private:
bool locked_;
int attemptCounter_;
int unlockLevel_;
std::vector currentSeed_;
};
7.4 CAN-TP 分包器(发送方)

// 将长 UDS 报文拆分为 SF/FF/CF,并通过回调发送 CAN 帧
class CanTpSplitter {
public:
using CanTxCallback = std::function& frameData)>;

void SetTxCallback(CanTxCallback cb) { txCb_ = cb; }

// 发送 UDS 报文(含完整应用层数据)
void SendUdsMessage(uint32_t targetCanId, const std::vector& udsData) {
if (udsData.size() <= 7) {
// 单帧
std::vector sf;
sf.push_back(static_cast(udsData.size())); // PCI = 0x0N
sf.insert(sf.end(), udsData.begin(), udsData.end());
txCb_(targetCanId, sf);
} else {
// 多帧:首帧
uint16_t totalLen = udsData.size();
std::vector ff;
ff.push_back(0x10 | ((totalLen >> 8) & 0x0F)); // 高4位=1, 低4位为长度高4位
ff.push_back(totalLen & 0xFF);
// 复制前 6 字节数据(FF 已占 2 字节 PCI,剩余 6 字节载荷)
size_t copyLen = std::min(6, udsData.size());
ff.insert(ff.end(), udsData.begin(), udsData.begin() + copyLen);
txCb_(targetCanId, ff);

// 后续连续帧
size_t offset = copyLen;
uint8_t sn = 1;
while (offset < udsData.size()) {
std::vector cf;
cf.push_back(0x20 | (sn & 0x0F));
size_t chunk = std::min(7, udsData.size() - offset);
cf.insert(cf.end(), udsData.begin() + offset, udsData.begin() + offset + chunk);
txCb_(targetCanId, cf);
offset += chunk;
sn = (sn + 1) & 0x0F;
// 实际需考虑 FC 流控,这里简化:若 BS 限制则需等待
// 以下为模拟等待 FC,实际应异步处理
if (offset < udsData.size()) {
// 应当等待接收 FC 后继续,此处演示简单延时
std::this_thread::sleep_for(std::chrono::milliseconds(5));
}
}
}
}

private:
CanTxCallback txCb_;
};
7.5 CAN-TP 组包器(接收方)

// 接收 CAN 帧,重组 UDS 报文,并在完整后回调
class CanTpReceiver {
public:
using UdsIndicationCallback = std::function& udsMsg)>;

void SetIndicationCallback(UdsIndicationCallback cb) { indCb_ = cb; }

// 处理收到的 CAN 帧(已剥离 CAN ID)
void OnCanFrameReceived(uint32_t srcCanId, const std::vector& frameData) {
if (frameData.empty()) return;
uint8_t pci = frameData[0];
uint8_t frameType = pci >> 4;

if (frameType == 0) { // 单帧
uint8_t len = pci & 0x0F;
std::vector uds(frameData.begin() + 1, frameData.begin() + 1 + len);
indCb_(srcCanId, uds);
} else if (frameType == 1) { // 首帧
uint16_t totalLen = ((pci & 0x0F) << 8) | frameData[1];
currentUds_.clear();
currentUds_.reserve(totalLen);
// 复制载荷(6 字节)
size_t copyLen = std::min(6, frameData.size() - 2);
currentUds_.insert(currentUds_.end(), frameData.begin() + 2, frameData.begin() + 2 + copyLen);
expectedSn_ = 1;
currentSrcId_ = srcCanId;
// 回复流控帧(FC)
SendFlowControl(srcCanId, 0, 0); // BS=0, STmin=0 表示无限制
} else if (frameType == 2) { // 连续帧
uint8_t sn = pci & 0x0F;
if (sn != expectedSn_) {
// 序列号错误,可发送溢出流控或丢弃
return;
}
currentUds_.insert(currentUds_.end(), frameData.begin() + 1, frameData.end());
expectedSn_ = (expectedSn_ + 1) & 0x0F;
// 若接收完成(实际需根据总长度判断)
if (currentUds_.size() >= currentUds_.capacity()) {
indCb_(currentSrcId_, currentUds_);
currentUds_.clear();
}
}
// 流控帧 (type=3) 为发送方处理,接收方无需处理
}

private:
void SendFlowControl(uint32_t targetId, uint8_t blockSize, uint8_t stMin) {
// 构造 FC 帧:0x30 + BS + STmin
std::vector fc = {0x30, blockSize, stMin};
// 假设可通过接口发送(模拟)
// canTx(targetId, fc);
}

uint32_t currentSrcId_;
std::vector currentUds_;
uint8_t expectedSn_;
UdsIndicationCallback indCb_;
};
8. 综合示例:Bootloader 刷写流程(UDS 0x34/36/37)

固件升级是 UDS 最典型的应用场景,顺序如下:

  1. 切换会话:10 02→ 编程会话

  2. 安全访问:27 01/27 02→ 解锁

  3. 请求下载:34 → 告知下载地址和大小

  4. 传输数据:循环36 → 分块传输(每块通常 4096 字节,通过 CAN-TP 分包)

  5. 请求结束传输:37→ 完成下载

  6. 校验程序:31 01 FF00(例程控制)→ 执行 CRC 校验

  7. 软复位:11 01→ ECU 复位进入新程序

每一步都需要处理否定响应(如 NRC 0x33 安全访问未解锁),并设置超时重试机制。
9. 总结

UDS 诊断协议是一个庞大但高度结构化的体系,掌握它需要理解:

  • 应用层服务的语义(SID/子功能/NRC)

  • 传输层多帧通信机制(CAN-TP 的 SF/FF/CF/FC 状态机)

  • 安全与状态管理(会话切换、安全访问、DTC 老化)

在 C++ 实现中,应注重模块化:分离应用层解析器、传输层组包/拆包器、会话状态机,并借助回调/异步设计适应真实嵌入式环境(RTOS 或事件驱动)。

本文提供的代码框架可直接扩展为生产级诊断栈,但实际工程还需考虑:

  • 超时与重传(应用层和传输层定时器)

  • 错误恢复与日志

  • 跨平台兼容性(端序、对齐)

希望本文能为读者的面试准备或项目开发提供系统性的知识图谱与实用代码参考。

参考资料:

  • ISO 14229-1:2020 Road vehicles — Unified diagnostic services (UDS)

  • ISO 15765-2:2016 Road vehicles — Diagnostic communication over Controller Area Network (DoCAN)

  • AUTOSAR Specification of Diagnostic Communication (SWS_DCM)

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
湖南一男子拾荒21年后领得42万养老金:当过国企工人,下岗后一直未缴费以为领不到

湖南一男子拾荒21年后领得42万养老金:当过国企工人,下岗后一直未缴费以为领不到

潇湘晨报
2026-09-27 20:04:27
2-1!世界第9征服客场,新帅哈维收获首胜,23岁天才梅开二度

2-1!世界第9征服客场,新帅哈维收获首胜,23岁天才梅开二度

足球狗说
2026-09-28 01:52:53
叶一茜携女儿九寨沟出游,森碟亭亭玉立,优秀家教令人赞叹

叶一茜携女儿九寨沟出游,森碟亭亭玉立,优秀家教令人赞叹

娱你同欢
2026-09-27 17:47:39
其实很多人活不过70岁

其实很多人活不过70岁

A活着
2026-09-27 09:05:25
北口榛花绝望大哭!严子怡难以逾越,日本网友:怪物必破世界纪录

北口榛花绝望大哭!严子怡难以逾越,日本网友:怪物必破世界纪录

杨华评论
2026-09-28 02:22:51
“刘欢被去世官方紧急辟谣”,自媒体造谣还有没有底线?

“刘欢被去世官方紧急辟谣”,自媒体造谣还有没有底线?

评底郭
2026-09-27 15:56:37
确认了!她系台湾间谍情报机关人员

确认了!她系台湾间谍情报机关人员

焦作日报
2026-09-27 15:33:27
日媒:严子怡一枪砸穿日本纪录 日本网友:她去参加男子比赛也会赢

日媒:严子怡一枪砸穿日本纪录 日本网友:她去参加男子比赛也会赢

劲爆体坛
2026-09-27 23:15:02
塞尔维亚总统武契奇宣布辞职

塞尔维亚总统武契奇宣布辞职

澎湃新闻
2026-09-28 02:47:02
西贝又上热搜了,不是罗永浩,是俩探店博主线下吃出来的热度。

西贝又上热搜了,不是罗永浩,是俩探店博主线下吃出来的热度。

荆楚寰宇文枢
2026-09-27 20:53:44
全民化债的时代已经来了。

全民化债的时代已经来了。

老陆不老
2026-09-27 20:06:06
陈妤颉:100米金牌是成年礼,200米银牌是教训

陈妤颉:100米金牌是成年礼,200米银牌是教训

澎湃新闻
2026-09-27 19:53:17
全世界感叹:新的世界秩序已经形成,两个超级大国时代开启

全世界感叹:新的世界秩序已经形成,两个超级大国时代开启

农夫史记
2026-09-27 19:57:36
妻子曝刘欢真正死因!独女是诱因,错过5年抢救期,一度恶化致死

妻子曝刘欢真正死因!独女是诱因,错过5年抢救期,一度恶化致死

风月得自难寻
2026-09-27 18:01:52
亚运会女单金牌得主诞生!王曼昱4-2险胜孙颖莎,摘得生涯第2冠

亚运会女单金牌得主诞生!王曼昱4-2险胜孙颖莎,摘得生涯第2冠

乒谈
2026-09-27 20:58:07
宫鲁鸣是否下课悬念揭晓,赛后发言惹众怒,郑薇一针见血太厉害

宫鲁鸣是否下课悬念揭晓,赛后发言惹众怒,郑薇一针见血太厉害

宗介说体育
2026-09-27 19:13:06
刘欢临终细节被曝!含泪离世,老婆女儿都守在身旁,母女俩太痛苦

刘欢临终细节被曝!含泪离世,老婆女儿都守在身旁,母女俩太痛苦

观察鉴娱
2026-09-27 10:19:27
惊天警报!久明派急速夺权,克里姆林宫权力更迭已进入最后倒计时

惊天警报!久明派急速夺权,克里姆林宫权力更迭已进入最后倒计时

军情观察家
2026-09-27 22:34:40
豹纹比基尼照刷屏后,这位韩国女演员的新剧也定了

豹纹比基尼照刷屏后,这位韩国女演员的新剧也定了

浅遇时光
2026-09-27 02:25:32
吴艳妮获铜牌!媒体人:这项目在亚洲已不领先,差距非常可怕

吴艳妮获铜牌!媒体人:这项目在亚洲已不领先,差距非常可怕

奥拜尔
2026-09-27 19:45:37
2026-09-28 04:51:00
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
1015文章数 348关注度
往期回顾 全部

科技要闻

星舰第14飞,为什么准备绕地球六圈?

头条要闻

孙颖莎2比4不敌王曼昱摘银 称可能等不到下届亚运会了

头条要闻

孙颖莎2比4不敌王曼昱摘银 称可能等不到下届亚运会了

体育要闻

114项指控成立,曼城已经完蛋了吗?

娱乐要闻

刘欢去世后谣言四起,韩磊被翻旧账

财经要闻

“为了看短剧,我妈两年花了22万 ”

汽车要闻

MAZDA EZ-60激光版上市 焕新全系11.39万元起

态度原创

艺术
数码
手机
亲子
房产

艺术要闻

千年松树开花,百年难遇!第一眼就惊艳了

数码要闻

10499元 微星Claw 8 EX AI+上新:搭载Arc G3处理器、睿频可达4.6GHz

手机要闻

iQOO16影像细节再剧透,主摄样张公布

亲子要闻

工程车小故事:洗澡澡

房产要闻

全年霸榜TOP1!南海・叁號院周年官宣:新作即将登场

无障碍浏览 进入关怀版