SNMP c++实现

背景

学c++想通过源码来熟悉,朋友推荐SNMP,顺便记录下学习过程。

SNMP 协议标准

参考 www.net-snmp.org/ 里面有如下SNMP介绍

SNMP is a widely used protocol for monitoring the health and welfare of network equipment (eg. routers), computer equipment and even devices like UPSs. Net-SNMP is a suite of applications used to implement SNMP v1, SNMP v2c and SNMP v3 using both IPv4 and IPv6

这里面提了三个版本

  • v1 RFC 1157
  • v2 RFC 1901
  • v3 RFC 2571

snmp v1版本

协议地址

www.rfc-editor.org/rfc/rfc1157...

之后的基于谷歌翻译进行整理

1协议状态

本备忘录,逻辑远程用户可以检查或更改网络元素的管理信息。
这些文档描述管理信息结构和配套备忘录一起为管理基于 TCP/IP 的互联网
(尤其是互联网)提供了一种简单、可行的架构和系统

2协议简介

yaml 复制代码
IAB 建议制定互联网网络管理标准,这是一项双管齐下的战略对基于 TCP/IP 的互联网进行网络管理。
短期内,简单网络管理协议(SNMP)将成为用于管理互联网社区中的节点。
制定了两个文档来定义管理信息:

RFC 1065,定义了管理信息结构(SMI)以及
RFC 1066,定义了管理信息库(MIB)

IAB 已指定 SNMP、SMI 和初始 Internet MIB 给完全符合"标准协议"且状态为"推荐"。
通过此行动,IAB建议所有IP和TCP实现都网络可管理,
并且网络的实现可管理的预计将采用和实施 SMI、MIB 和SNMP。

当前基于 TCP/IP 的网络管理框架互联网包括:
管理结构和识别基于 TCP/IP 的互联网信息,描述了如何管理MIB 中包含的对象定义在RFC 1155中;
TCP/IP 网络管理的管理信息库基于互联网,它描述了包含在RFC 1156中规定的 MIB ;
以及简单网络管理协议,定义用于管理这些对象的协议,如本备忘录中阐明

IAB 建议制定互联网网络管理规范、互联网活动董事会已指示互联网工程任务组 (IETF)
在网络管理领域建立两个新的工作组。
一个小组负责进一步规范和定义管理信息库 (MIB) 中要包含的元素。
另一人负责定义对简单网络管理协议(SNMP)以适应短期网络供应商和运营社区的需求,并协调
与 MIB 工作组的输出一致

MIB 工作组发布了两份备忘录,其中一份定义了管理信息结构 (SMI)供管理 MIB 中包含的对象。
第二份备忘录定义了管理对象
SNMP 扩展工作组的成果是本备忘录,其中纳入了对初始 SNMP 定义的更改,需要与 MIB 工作组的输出保持一致

3 体系结构

3体系结构

scss 复制代码
SNMP 体系结构模型中隐含着网络管理站和网络元素的集合。

网络管理站执行管理应用程序来监视和控制网络元素。

网络元素是诸如主机、网关、终端服务器等设备,
它们具有管理代理,负责执行网络管理站请求的网络管理功能。

简单网络管理协议 (SNMP) 用于在网络管理站和网络元素中的代理之间传递管理信息

3.2.4协议交换的形式和含义

在 SNMP 中,管理实体之间的管理信息通信这些消息的形式和含义在下面的第 4 节中定义。

与最小化管理代理复杂性的目标一致,SNMP 消息的交换只需要不可靠的数据报服务,
并且每条消息都完全且独立地由单个传输数据报表示。

虽然本文档指定了通过 UDP 协议的消息交换,但SNMP 的机制通常适用于各种传输服务

3.2.5管理关系的定义

sql 复制代码
体系结构允许参与协议的实体之间存在各种管理
驻留在管理站和网络元素上使用 SNMP 相互通信的实体称为 SNMP应用程序实体。
实现 SNMP 并因此支持 SNMP 应用程序实体的对等进程称为协议实体

SNMP 代理与任意一组 SNMP 应用程序实体的配对称为 SNMP 社区。
每个 SNMP社区都由一个八位字节字符串命名,该字符串称为该社区的社区名称。
   
由 SNMP 应用程序实体发起的 SNMP 消息
实际上属于由该消息的社区组件命名的 SNMP 社区,该消息称为真实 SNMP 消息。
   
将 SNMP 消息识别为特定 SNMP 社区的真实 SNMP 消息的称为身份验证方案。
根据一个或多个身份验证方案识别真实 SNMP 消息的功能的实现身份验证服务

对于任何网络元素,MIB 中与该元素相关的对象子集称为 SNMP MIB 视图
集合 { READ-ONLY, READ-WRITE } 的元素称为 SNMP访问模式

访问模式与 SNMP MIB 视图的配对称为SNMP 社区配置文件
SNMP 社区配置文件表示对指定 MIB 视图中变量的指定访问权限

社区与 SNMP 社区配置文件的配对称为SNMP 访问策略。
访问策略表示由指定 SNMP 社区的 SNMP 代理向该社区的其他成员提供的指定社区配置文件

SNMP应用程序实体之间的所有管理关系都是根据 SNMP 访问策略在架构上定义的

对于每个 SNMP 访问策略,
如果指定 SNMP 社区的 SNMP 代理所在的网络元素不是指定配置文件的 MIB 视图所属的网络元素,
则该策略称为 SNMP 代理访问策略

与代理访问策略关联的 SNMP 代理称为 SNMP 代理代理

4协议规范

scss 复制代码
网络管理协议是一种应用协议,通过它可以检查或更改代理的 MIB 变量。

协议实体之间的通信是通过交换消息来实现的使用 ASN.1 的基本编码规则
在单个 UDP 数据报中完全独立地表示(如第 3.2.2 节所述)。

消息由版本标识符、SNMP 社区名称和协议数据单元 (PDU) 组成。

关联的主机上的 UDP 端口 161 上接收traps的消息之外的所有消息
(即除包含 Trap-PDU 的消息之外的所有消息)。

报告traps的消息应在 UDP 端口 162 上接收以进行进一步处理

 所有 SNMP 实现都必须支持这五个PDU:  
   GetRequest-PDU, 
   GetNextRequest-PDU, 
   GetResponse-PDU,
   SetRequest-PDU, 
   Trap-PDU

4.1 定义

sql 复制代码
    RFC1157-SNMP DEFINITIONS ::= BEGIN

     IMPORTS
          ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks
                  FROM RFC1155-SMI;

     -- top-level message

             Message ::=
                     SEQUENCE {
                          version        -- version-1 for this RFC
                             INTEGER {
                                 version-1(0)
                             },

                         community      -- community name
                             OCTET STRING,

                         data           -- e.g., PDUs if trivial
                             ANY        -- authentication is being used
                     }

     -- protocol data units

             PDUs ::=
                     CHOICE {
                         get-request
                             GetRequest-PDU,

                         get-next-request
                             GetNextRequest-PDU,

                         get-response
                             GetResponse-PDU,

                         set-request
                             SetRequest-PDU,

                         trap
                             Trap-PDU
                          }

     -- the individual PDUs and commonly used
     -- data types will be defined later

     END

这里使用了一种 ASN.1 的基本编码规则,使用ds能查到相关的规则

ASN.1(Abstract Syntax Notation One,抽象语法表示法)

是一种用于描述数据结构和编码规则的国际标准(由 ITU-T X.680 和 X.690 定义), 广泛应用于网络协议(如 SNMP、LDAP、X.509 证书)中。

以下是其核心语法和编码规则的详细说明: 一、ASN.1 语法

  1. 基本数据类型 ASN.1 定义了多种基础数据类型,以下是常见类型:
类型 描述 示例(ASN.1 定义)
INTEGER 整数 counter INTEGER ::= 42
BOOLEAN 布尔值(TRUE/FALSE) enabled BOOLEAN ::= TRUE
OCTET STRING 字节序列(二进制或字符串) name OCTET STRING ::= "DeviceA"
NULL 空值 empty NULL ::= NULL
OBJECT IDENTIFIER 全局唯一标识符(OID) sysDescr OID ::= { 1.3.6.1.2.1.1.1 }
SEQUENCE 有序结构体(类似结构体) Person ::= SEQUENCE {<br> name OCTET STRING,<br> age INTEGER }
SEQUENCE OF 同类型元素的列表 PortList ::= SEQUENCE OF INTEGER
CHOICE 多选一的结构 Value ::= CHOICE {<br> intVal INTEGER,<br> strVal OCTET STRING }

  1. 模块定义 ASN.1 通过模块(Module)组织数据结构的定义,语法如下:
asn.1 复制代码
ModuleName DEFINITIONS ::= BEGIN
  -- 类型和值的定义
END

示例(定义一个 SNMP MIB 对象):

asn.1 复制代码
SNMP-MIB DEFINITIONS ::= BEGIN
  sysUpTime OBJECT-TYPE
    SYNTAX      INTEGER (0..4294967295)
    MAX-ACCESS  read-only
    STATUS      current
    DESCRIPTION "系统运行时间(单位:0.01秒)"
    ::= { system 3 }
END

  1. 对象标识符(OID) • OID 是一个树状结构的全局唯一标识符,用于标识被管理对象(如 SNMP 中的 MIB 对象)。 • 语法 :用点分十进制表示,例如 1.3.6.1.2.1.1.1 对应 iso.org.dod.internet.mgmt.mib-2.system.sysDescr

  1. 宏(MACRO) • ASN.1 支持通过宏(MACRO)扩展自定义语法(如 SNMP 中的 OBJECT-TYPE 宏):
asn.1 复制代码
OBJECT-TYPE MACRO ::= BEGIN
  TYPE NOTATION ::= "SYNTAX" type "ACCESS" access "STATUS" status 
  VALUE NOTATION ::= value(VALUE OBJECT IDENTIFIER)
END

二、ASN.1 编码规则 ASN.1 定义了多种编码规则,将数据结构转换为二进制或文本格式。常见规则包括:

  1. BER(Basic Encoding Rules)用途 :SNMPv1/v2c 使用 BER 编码。 • 编码格式 :每个数据元素由 标识符(Tag)长度(Length)值(Value) 组成(TLV 结构)。 • 示例 :整数 42 的 BER 编码:

    plaintext 复制代码
    02 01 2A
    ├── 02: 标识符(INTEGER 类型)
    ├── 01: 长度(1字节)
    └── 2A: 值(十六进制的 42)

IMPORTS 关键字用于从其他模块中引入(导入)已定义的数据类型或值

最开始的定义引用了SMI的定义,从1155中复制过来
sql 复制代码
                -- names of objects in the MIB

               ObjectName ::=
                   OBJECT IDENTIFIER
				   
               -- syntax of objects in the MIB

               ObjectSyntax ::=
                   CHOICE {
                       simple
                           SimpleSyntax,

               -- note that simple SEQUENCEs are not directly
               -- mentioned here to keep things simple (i.e.,
               -- prevent mis-use).  However, application-wide
               -- types which are IMPLICITly encoded simple
               -- SEQUENCEs may appear in the following CHOICE

                       application-wide
                           ApplicationSyntax
                   }

                  SimpleSyntax ::=
                      CHOICE {
                          number
                              INTEGER,

                          string
                              OCTET STRING,

                          object
                              OBJECT IDENTIFIER,

                          empty
                              NULL
                      }

                  ApplicationSyntax ::=
                      CHOICE {
                          address
                              NetworkAddress,

                          counter
                              Counter,

                          gauge
                              Gauge,

                          ticks
                              TimeTicks,

                          arbitrary
                              Opaque




                  -- other application-wide types, as they are
                  -- defined, will be added here
                      }


                  -- application-wide types

                  NetworkAddress ::=
                      CHOICE {
                          internet
                              IpAddress
                      }

                  IpAddress ::=
                      [APPLICATION 0]          -- in network-byte order
                          IMPLICIT OCTET STRING (SIZE (4))

                  Counter ::=
                      [APPLICATION 1]
                          IMPLICIT INTEGER (0..4294967295)

                  Gauge ::=
                      [APPLICATION 2]
                          IMPLICIT INTEGER (0..4294967295)

                  TimeTicks ::=
                      [APPLICATION 3]
                          IMPLICIT INTEGER (0..4294967295)

                  Opaque ::=
                      [APPLICATION 4]          -- arbitrary ASN.1 value,
                          IMPLICIT OCTET STRING   --   "double-wrapped"

这上面出现了一个 APPLICATION的标签

ASN.1 定义了 4 类标签,用于区分不同类型的上下文:

标签类 说明
UNIVERSAL 通用标签,预定义类型(如 INTEGEROCTET STRING)必须使用此类标签。
APPLICATION 应用范围标签,用于某个特定应用(如 SNMP、LDAP)内部的自定义类型。
CONTEXT-SPECIFIC 上下文相关标签,仅在某个结构(如 SEQUENCE)内部有效。
PRIVATE 私有标签,供组织内部使用。
asn.1 复制代码
TimeTicks ::= [APPLICATION 3] IMPLICIT INTEGER (0..4294967295)
• **APPLICATION 3**:表示这是一个 **应用范围的自定义类型**,标签号为 `3`。
• **IMPLICIT**:表示编码时直接使用 `APPLICATION 3` 标签,而不是继承基类型(`INTEGER`)的 UNIVERSAL 标签。

3. 编码示例**
假设 `TimeTicks` 值为 `12345`(即 123.45秒):
• **默认编码(无标签)**:  
  作为普通 `INTEGER` 会被编码为 `02 02 30 39`(`0x02` 是 UNIVERSAL 标签)。
• **使用 `APPLICATION 3` 标签后**:  
  编码为 `43 02 30 39`:
  • `43` = `APPLICATION 3` 的标签号(`0x40` 表示 APPLICATION 类,`0x03` 是标签值,故 `0x40 + 0x03 = 0x43`)。
  • `02` = 长度(2字节)。
  • `30 39` = 值 `12345` 的十六进制(`0x3039`)。

4.1.1 常用的ASN.1 constructs used frequently

scss 复制代码
                  -- request/response information

                  RequestID ::=
                          INTEGER

                  ErrorStatus ::=
                          INTEGER {
                              noError(0),
                              tooBig(1),
                              noSuchName(2),
                              badValue(3),
                              readOnly(4)
                              genErr(5)
                          }

                  ErrorIndex ::=
                          INTEGER


                  -- variable bindings

                  VarBind ::=
                          SEQUENCE {
                              name
                                  ObjectName,

                              value
                                  ObjectSyntax
                          }

                  VarBindList ::=
                          SEQUENCE OF
                              VarBind

4.1.2 The GetRequest-PDU

由协议实体生成收到 GetRequest-PDU 后, 接收协议实体根据下面列表中的任何适用规则进行响应

接收协议实体向接收消息的发起者发送GetResponse-PDU

lua 复制代码
                  GetRequest-PDU ::=
                      [0]
                          IMPLICIT SEQUENCE {
                              request-id
                                  RequestID,

                              error-status        -- always 0
                                  ErrorStatus,

                              error-index         -- always 0
                                  ErrorIndex,

                              variable-bindings
                                  VarBindList
                          }

需要检查 variable-bindings 处理noSuchName异常以及genErr异常, 检查是否超过本地限制tooBig

scss 复制代码
noError(0),tooBig(1),noSuchName(2),genErr(5)

4.1.3 GetNextRequest-PDU

GetNextRequest-PDU 的格式与 GetRequest-PDU 的格式相同, 只是 PDU 类型的指示不同

GetNextRequest-PDU 仅由协议实体在其 SNMP 应用实体的请求下生成。 在收到 GetNextRequest-PDU 后, 接收协议实体将根据以下列表中的任何适用规则作出响应

ini 复制代码
         Destination                     NextHop         Metric

         10.0.0.99                       89.1.1.42       5
         9.1.2.3                         99.0.0.3        3
         10.0.0.51                       89.1.1.42       5


   The management station sends to the SNMP agent a GetNextRequest-PDU
   containing the indicated OBJECT IDENTIFIER values as the requested
   variable names:

   GetNextRequest ( ipRouteDest, ipRouteNextHop, ipRouteMetric1 )


   The SNMP agent responds with a GetResponse-PDU:

                 GetResponse (( ipRouteDest.9.1.2.3 =  "9.1.2.3" ),
                         ( ipRouteNextHop.9.1.2.3 = "99.0.0.3" ),
                         ( ipRouteMetric1.9.1.2.3 = 3 ))


   The management station continues with:

                 GetNextRequest ( ipRouteDest.9.1.2.3,
                         ipRouteNextHop.9.1.2.3,
                         ipRouteMetric1.9.1.2.3 )


   The SNMP agent responds:

                 GetResponse (( ipRouteDest.10.0.0.51 = "10.0.0.51" ),
                         ( ipRouteNextHop.10.0.0.51 = "89.1.1.42" ),
                         ( ipRouteMetric1.10.0.0.51 = 5 ))


   The management station continues with:

                 GetNextRequest ( ipRouteDest.10.0.0.51,
                         ipRouteNextHop.10.0.0.51,
                         ipRouteMetric1.10.0.0.51 )


   The SNMP agent responds:

                 GetResponse (( ipRouteDest.10.0.0.99 = "10.0.0.99" ),
                         ( ipRouteNextHop.10.0.0.99 = "89.1.1.42" ),
                         ( ipRouteMetric1.10.0.0.99 = 5 ))


   The management station continues with:

                 GetNextRequest ( ipRouteDest.10.0.0.99,
                         ipRouteNextHop.10.0.0.99,
                         ipRouteMetric1.10.0.0.99 )
                         
As there are no further entries in the table, the SNMP agent returns
   those objects that are next in the lexicographical ordering of the
   known object names.  This response signals the end of the routing
   table to the management station.

4.1.4. The GetResponse-PDU

GetResponse-PDU 的格式与 GetRequest-PDU 的格式相同, 只是 PDU 类型指示不同

接收到 GetRequest-PDU、GetNextRequest-PDU 或 SetRequest-PDU 协议实体才会生成 GetResponse-PDU如本文档其他地方所述。

在收到 GetResponse-PDU 后, 接收协议实体会将其内容呈现给其 SNMP 应用程序实体

4.1.5 SetRequest -PDU

SetRequest-PDU 的格式与 GetRequest-PDU 相同, 只是 PDU 类型指示不同

SNMP 应用程序实体的请求后,协议实体才会生成 SetRequest-PDU 收到 SetRequest-PDU 后, 接收实体根据下面列表中的任何适用规则进行响应

4.1.6. The Trap-PDU

Trap-PDU 格式 :

sql 复制代码
     Trap-PDU ::=
         [4]

              IMPLICIT SEQUENCE {
                 enterprise          -- type of object generating
                                     -- trap, see sysObjectID in [5]
                     OBJECT IDENTIFIER,

                 agent-addr          -- address of object generating
                     NetworkAddress, -- trap

                 generic-trap        -- generic trap type
                     INTEGER {
                         coldStart(0),
                         warmStart(1),
                         linkDown(2),
                         linkUp(3),
                         authenticationFailure(4),
                         egpNeighborLoss(5),
                         enterpriseSpecific(6)
                     },

                 specific-trap     -- specific code, present even
                     INTEGER,      -- if generic-trap is not
                                   -- enterpriseSpecific

                 time-stamp        -- time elapsed between the last
                   TimeTicks,      -- (re)initialization of the network
                                   -- entity and the generation of the
                                      trap

                 variable-bindings   -- "interesting" information
                      VarBindList
             }

SNMP 应用程序实体的请求下,协议实体才会生成 Trap-PDU

实体选择 SNMP 应用程序实体的目标地址的方式是特定于实现的。

在收到 Trap-PDU 后,接收协议实体将其内容呈现给其 SNMP 应用程序实体 Trap-PDU 的变量绑定组件的意义与实现有关。

5 定义

sql 复制代码
     RFC1157-SNMP DEFINITIONS ::= BEGIN

      -- IMPORTS ObjectName, ObjectSyntax, NetworkAddress, IpAddress, TimeTicks FROM RFC1155-SMI;
      
               -- names of objects in the MIB

               ObjectName ::=
                   OBJECT IDENTIFIER
				   
               -- syntax of objects in the MIB

               ObjectSyntax ::=
                   CHOICE {
                       simple
                           SimpleSyntax,

               -- note that simple SEQUENCEs are not directly
               -- mentioned here to keep things simple (i.e.,
               -- prevent mis-use).  However, application-wide
               -- types which are IMPLICITly encoded simple
               -- SEQUENCEs may appear in the following CHOICE

                       application-wide
                           ApplicationSyntax
                   }

                  SimpleSyntax ::=
                      CHOICE {
                          number
                              INTEGER,

                          string
                              OCTET STRING,

                          object
                              OBJECT IDENTIFIER,

                          empty
                              NULL
                      }

                  ApplicationSyntax ::=
                      CHOICE {
                          address
                              NetworkAddress,

                          counter
                              Counter,

                          gauge
                              Gauge,

                          ticks
                              TimeTicks,

                          arbitrary
                              Opaque




                  -- other application-wide types, as they are
                  -- defined, will be added here
                      }


                  -- application-wide types

                  NetworkAddress ::=
                      CHOICE {
                          internet
                              IpAddress
                      }

                  IpAddress ::=
                      [APPLICATION 0]          -- in network-byte order
                          IMPLICIT OCTET STRING (SIZE (4))

                  Counter ::=
                      [APPLICATION 1]
                          IMPLICIT INTEGER (0..4294967295)

                  Gauge ::=
                      [APPLICATION 2]
                          IMPLICIT INTEGER (0..4294967295)

                  TimeTicks ::=
                      [APPLICATION 3]
                          IMPLICIT INTEGER (0..4294967295)

                  Opaque ::=
                      [APPLICATION 4]          -- arbitrary ASN.1 value,
                          IMPLICIT OCTET STRING   --   "double-wrapped"
      


          -- top-level message

          Message ::=
                  SEQUENCE {
                      version          -- version-1 for this RFC
                          INTEGER {
                              version-1(0)
                          },

                      community        -- community name
                          OCTET STRING,

                      data             -- e.g., PDUs if trivial
                          ANY          -- authentication is being used
                  }


          -- protocol data units

          PDUs ::=
                  CHOICE {
                              get-request
                                  GetRequest-PDU,

                              get-next-request
                                  GetNextRequest-PDU,

                              get-response
                                  GetResponse-PDU,

                              set-request
                                  SetRequest-PDU,

                              trap
                                  Trap-PDU
                          }


          -- PDUs

          GetRequest-PDU ::=
              [0]
                  IMPLICIT PDU

          GetNextRequest-PDU ::=
              [1]
                  IMPLICIT PDU

          GetResponse-PDU ::=
              [2]
                  IMPLICIT PDU

          SetRequest-PDU ::=
              [3]
                  IMPLICIT PDU

          PDU ::=
                  SEQUENCE {
                     request-id
                          INTEGER,

                      error-status      -- sometimes ignored
                          INTEGER {
                              noError(0),
                              tooBig(1),
                              noSuchName(2),
                              badValue(3),
                              readOnly(4),
                              genErr(5)
                          },

                      error-index       -- sometimes ignored
                         INTEGER,

                      variable-bindings -- values are sometimes ignored
                          VarBindList
                  }

          Trap-PDU ::=
              [4]
                 IMPLICIT SEQUENCE {
                      enterprise        -- type of object generating
                                        -- trap, see sysObjectID in [5]


                          OBJECT IDENTIFIER,

                      agent-addr        -- address of object generating
                          NetworkAddress, -- trap

                      generic-trap      -- generic trap type
                          INTEGER {
                              coldStart(0),
                              warmStart(1),
                              linkDown(2),
                              linkUp(3),
                              authenticationFailure(4),
                              egpNeighborLoss(5),
                              enterpriseSpecific(6)
                          },

                      specific-trap  -- specific code, present even
                          INTEGER,   -- if generic-trap is not
                                     -- enterpriseSpecific

                      time-stamp     -- time elapsed between the last
                          TimeTicks, -- (re)initialization of the
                                        network
                                     -- entity and the generation of the
                                        trap

                       variable-bindings -- "interesting" information
                          VarBindList
                  }


          -- variable bindings

          VarBind ::=
                  SEQUENCE {
                      name
                          ObjectName,

                      value
                          ObjectSyntax
                  }

         VarBindList ::=
                  SEQUENCE OF
                     VarBind

         END
相关推荐
鄃鳕1 小时前
更新vscode ,将c++11更新到c++20
c++·vscode·c++20
Dream it possible!7 小时前
LeetCode 热题 100_字符串解码(71_394_中等_C++)(栈)
c++·算法·leetcode
My Li.8 小时前
c++的介绍
开发语言·c++
邪恶的贝利亚10 小时前
C++之序列容器(vector,list,dueqe)
开发语言·c++
原来是猿10 小时前
蓝桥备赛(13)- 链表和 list(上)
开发语言·数据结构·c++·算法·链表·list
成功助力英语中国话10 小时前
SDK编程,MFC编程,WTL编程之间的关系
c++·mfc
仟濹11 小时前
【算法 C/C++】二维差分
c语言·c++·算法
总斯霖11 小时前
题解:士兵排列
数据结构·c++·算法
稳兽龙11 小时前
P4268 [USACO18FEB] Directory Traversal G
c++·算法·换根dp
放氮气的蜗牛12 小时前
C++从入门到精通系列教程之第十篇:异常处理与调试技巧
开发语言·jvm·c++