NS3:FlowMonitor设计讲解

  • 各有关类的描述与说明
  • FlowMonitor模块详解
    • 模块描述
    • 设计
    • 适用范围和限制
    • 用例
    • 有关助手
    • 属性设置
    • 有关输出
    • 协议的代表含义(TCP/UDP, AODV/OLSR)
    • 已经有的使用的例子
    • 故障排除
      • ns-3.34/examples/matrix-topology/matrix-topology.cc 出现 indefined reference
  • 示例代码
  • FlowMonitor实例的分析文件:manet-routing-compare.cc
  • 用flowmonitor中的不同端口统计业务信息(用户数据)和路由控制信息(路由开销)
  • 参考文件

各有关类的描述与说明

  • 每个仿真只有一个FlowMonitor(后面会做详细解释)

  • 每个仿真只有一个FlowClassifier

    • 每个流分配唯一的整数标识
    • 包含映射参数的分类方法(例如,分组或分组报头)到相应的流标识符;
    • FlowClassifier是抽象的,需要一个具体的子类

      Ipv4FlowClassifier

  • 通常(但不一定)一个节点上一个流探针FlowProbe

    • 负责获取分组数据
    • 与FlowClassifier合作
    • FlowProbe是抽象的,需要一个具体的子类

      Ipv4FlowProbe

      • Ipv4FlowProbe需要一个匹配的分类器 Ipv4FlowClassifier
  • 每个FlowProbe的每个模拟流程对应一个ProbeFlowStats对象来统计从第一次探测直到此时探测中接收到数据包的信息

    • 按FlowId索引
    • 字节数
    • 分组数
    • 延时
  • 每个FlowMonitor的每个流对应一个EndToEndFlowStats,记录了

    • 丢包数
    • 丢字节数
    • 总字节数
    • 总包数
    • 端到端延时

FlowMonitor模块详解

模块描述

Flow Monitor模块的目标是提供一个灵活的系统来衡量网络协议的性能。 该模块使用安装在网络节点中的探针来跟踪节点交换的数据包,并进行测量一些参数。 数据包根据它们所属的流进行划分,其中每个流根据探测器的特征定义(例如,对于IP包,数据被定义为五元组)

  • 协议
  • 源IP
  • 源端口
  • 目的IP
  • 目的端口

收集每个流的统计信息可以以XML格式导出。 此外,用户可以直接访问探针以请求关于每个流的特定统计数据。

设计

Flow Monitor模块采用模块化设计。 它可以通过继承ns3 :: FlowProbens3 :: FlowClassifier进行扩展。[FlowMonitor ]中描述了完整的模块设计。

适用范围和限制

目前,探针和分类器可用于IPv4和IPv6,每个探针将对分组进行跟踪和分类:

  • 发送数据包 (SendOutgoing IPv[4,6] 跟踪)
  • 转发数据包 (UnicastForward IPv[4,6] 跟踪)
  • 收到数据包 (LocalDeliver IPv[4,6] 跟踪)
  • 丢弃数据包(Drop IPv[4,6] 跟踪)

有关标签ns3::Ipv[4,6]FlowProbeTag将被添加到数据包中,基本数据包的数据将携带标签传输,这样可对数据包进行分类。

注意:因为在IP级别跟踪分组,探针将L4协议(例如,TCP)引起的重传作为新分组; 目前只对L4(TCP,UDP)数据包分类;只有单播数据包将被分类,这些限制可能在将来被删除。

为每个流收集的数据是:

  • timeFirstTxPacket: 传输流中第一个数据包时的时间
  • timeLastTxPacket:传输 流中最后一个数据包时的时间
  • timeFirstRxPacket:端节点接收到流中的第一个数据包的时间;
  • timeLastRxPacket: 收到流中的最后一个数据包的时间
  • delaySum: 所有收到的流数据包的所有端到端延迟的总和;
  • jitterSum:所有接收到的流数据包的所有端到端延迟抖动(延迟变化)值的总和,参考文档:rfc:3393;
  • txBytes, txPackets: 流的传输字节/数据包总数;
  • rxBytes, rxPackets: 流的接收字节/数据包总数;
  • lostPackets: 假设丢失的数据包总数(未报告超过10秒);
  • timesForwarded: 报告转发数据包的次数;
  • delayHistogram, jitterHistogram, packetSizeHistogram: 延迟,抖动和数据包大小的直方图
  • packetsDropped, bytesDropped: 丢失的数据包和字节数,根据丢失原因代码(在探测中定义)进行划分。

注意:探针测量的是包括IP头的包字节,L2标头有关信息不包含在度量范围内。

用例

用法::

 // Flow monitorPtr<FlowMonitor> flowMonitor;FlowMonitorHelper flowHelper;flowMonitor = flowHelper.InstallAll();Simulator::Stop (Seconds(stop_time));Simulator::Run ();flowMonitor->SerializeToXmlFile("NameOfFile.xml", true, true);

SerializeToXmlFile()第二第三个参数分别用于激活/停用直方图和每探针详细统计数据,其他可能的替代方案可以在Doxygen文档中找到。

有关助手

助手类:ns3 :: FlowMonitorHelper 在main中只实例化一次
此外助手API遵循普通助手的模式使用。通过帮助程序,您可以在节点中安装监视器,设置监视器属性并打印统计信息。

属性设置

ns3::FlowMonitor 类中有一下属性:

  • MaxPerHopDelay (Time, default 10s): 应考虑的最大每跳延迟;
  • StartTime (Time, default 0s): 监控开始的时间;
  • DelayBinWidth (double, default 0.001): 延迟直方图中使用的宽度;
  • JitterBinWidth (double, default 0.001): 抖动直方图中使用的宽度;
  • PacketSizeBinWidth (double, default 20.0): 分组直方图中使用的宽度;
  • FlowInterruptionsBinWidth (double, default 0.25): 流终端直方图中使用的宽度;
  • FlowInterruptionsMinTime (double, default 0.5): 最小到达间隔时间被视为流量中断。

有关输出

主要的输出是关于流统计信息的XML格式的报告。 一个例子是::

  <?xml version="1.0" ?><FlowMonitor><FlowStats><Flow flowId="1" timeFirstTxPacket="+0.0ns" timeFirstRxPacket="+20067198.0ns" timeLastTxPacket="+2235764408.0ns" timeLastRxPacket="+2255831606.0ns" delaySum="+138731526300.0ns" jitterSum="+1849692150.0ns" lastDelay="+20067198.0ns" txBytes="2149400" rxBytes="2149400" txPackets="3735" rxPackets="3735" lostPackets="0" timesForwarded="7466"></Flow></FlowStats><Ipv4FlowClassifier><Flow flowId="1" sourceAddress="10.1.3.1" destinationAddress="10.1.2.2" protocol="6" sourcePort="49153" destinationPort="50000" /></Ipv4FlowClassifier><Ipv6FlowClassifier></Ipv6FlowClassifier><FlowProbes><FlowProbe index="0"><FlowStats  flowId="1" packets="3735" bytes="2149400" delayFromFirstProbeSum="+0.0ns" ></FlowStats></FlowProbe><FlowProbe index="2"><FlowStats  flowId="1" packets="7466" bytes="2224020" delayFromFirstProbeSum="+199415389258.0ns" ></FlowStats></FlowProbe><FlowProbe index="4"><FlowStats  flowId="1" packets="3735" bytes="2149400" delayFromFirstProbeSum="+138731526300.0ns" ></FlowStats></FlowProbe></FlowProbes></FlowMonitor>

输出是由从10.1.3.1到10.1.2.2的TCP流生成的。

协议的代表含义(TCP/UDP, AODV/OLSR)

protocol=“6” 代表TCP
protocol=“17” 代表UDP
对于协议的 Port:654 代表 AODV ; 698 OLSR

值得注意的是,索引2探测器报告的数据包和其他探测器的字节数更多。
这是一种完全正常的行为,因为数据包在该节点的IP级别被分段。

还应该观察到接收节点的探测(索引4)不计算片段,因为重组在探测点之前完成。

已经有的使用的例子

src/flow-monitor/examples
此外,以下示例使用流量监视器的模块:

  • examples/matrix-topology/matrix-topology.cc
  • examples/routing/manet-routing-compare.cc
  • examples/routing/simple-global-routing.cc
  • examples/tcp/tcp-variants-comparison.cc
  • examples/wireless/multirate.cc
  • examples/wireless/wifi-hidden-terminal.cc

故障排除

不要在模拟中定义多个:ns3 :: FlowMonitorHelper

ns-3.34/examples/matrix-topology/matrix-topology.cc 出现 indefined reference

build/../examples/matrix-topology/matrix-topology.cc:297:对‘ns3::FlowMonitorHelper::FlowMonitorHelper()’未定义的引用
build/../examples/matrix-topology/matrix-topology.cc:298:对‘ns3::FlowMonitorHelper::InstallAll()’未定义的引用
build/../examples/matrix-topology/matrix-topology.cc:307:对‘ns3::FlowMonitor::SerializeToXmlFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, bool)’未定义的引用
build/../examples/matrix-topology/matrix-topology.cc:297:对‘ns3::FlowMonitorHelper::~FlowMonitorHelper()’未定义的引用
build/../examples/matrix-topology/matrix-topology.cc:297:对‘ns3::FlowMonitorHelper::~FlowMonitorHelper()’未定义的引用
  • 引入头文件:
#include "ns3/flow-monitor-module.h"
//#include "ns3/flow-monitor.h"
//#include "ns3/flow-monitor-helper.h"
  • 在example/matrix-topology/wscript 修改:
def build(bld):obj = bld.create_ns3_program('matrix-topology',['network', 'internet', 'netanim', 'point-to-point', 'mobility', 'applications','flow-monitor'])obj.source = 'matrix-topology.cc'

示例代码

代码可直接查看这篇ns3利用FlowMonitor进行网络性能分析

FlowMonitor实例的分析文件:manet-routing-compare.cc

#include "ns3/flow-monitor-helper.h" //头文件加上
Ptr<FlowMonitor> flowmon;FlowMonitorHelper flowmonHelper;flowmon = flowmonHelper.InstallAll ();NS_LOG_INFO ("Run Simulation.");CheckThroughput ();Simulator::Stop (Seconds (TotalTime));Simulator::Run ();flowmon->SerializeToXmlFile ((tr_name + ".flowmon").c_str(), false, false);// flowmon->SerializeToXmlFile ((tr_name + "HestandProbes.flowmon").c_str(), true, true);// 开启每个probe和直方图Simulator::Destroy ();
}

同时在FlowMonitor模块的example下面有:
wifi-olsr-flowmon.py 用python运行协议是UPD+OLSR
那么还有一个生成的xml文件的解析的 flowmon-parse-results.py 里面可以看到解析的 6: ‘TCP’, 17: ‘UDP’

from __future__ import division
import sys
import os
try:from xml.etree import cElementTree as ElementTree
except ImportError:from xml.etree import ElementTreedef parse_time_ns(tm):if tm.endswith('ns'):return float(tm[:-2])raise ValueError(tm)## FiveTuple
class FiveTuple(object):## class variables## @var sourceAddress #  source address## @var destinationAddress #  destination address## @var protocol #  network protocol## @var sourcePort #  source port## @var destinationPort #  destination port## @var __slots_ #  class variable list__slots_ = ['sourceAddress', 'destinationAddress', 'protocol', 'sourcePort', 'destinationPort']def __init__(self, el):'''! The initializer.@param self The object pointer.@param el The element.'''self.sourceAddress = el.get('sourceAddress')self.destinationAddress = el.get('destinationAddress')self.sourcePort = int(el.get('sourcePort'))self.destinationPort = int(el.get('destinationPort'))self.protocol = int(el.get('protocol'))## Histogram
class Histogram(object):## class variables## @var bins#  histogram bins## @var nbins#  number of bins## @var number_of_flows#  number of flows## @var __slots_#  class variable list__slots_ = 'bins', 'nbins', 'number_of_flows'def __init__(self, el=None):'''! The initializer.@param self The object pointer.@param el The element.'''self.bins = []if el is not None:#self.nbins = int(el.get('nBins'))for bin in el.findall('bin'):self.bins.append( (float(bin.get("start")), float(bin.get("width")), int(bin.get("count"))) )## Flow
class Flow(object):## class variables## @var flowId#  delay ID## @var delayMean#  mean delay## @var packetLossRatio#  packet loss ratio## @var rxBitrate#  receive bit rate## @var txBitrate#  transmit bit rate## @var fiveTuple#  five tuple## @var packetSizeMean#  packet size mean## @var probe_stats_unsorted#  unsirted probe stats## @var hopCount#  hop count## @var flowInterruptionsHistogram#  flow histogram## @var rx_duration#  receive duration## @var __slots_#  class variable list__slots_ = ['flowId', 'delayMean', 'packetLossRatio', 'rxBitrate', 'txBitrate','fiveTuple', 'packetSizeMean', 'probe_stats_unsorted','hopCount', 'flowInterruptionsHistogram', 'rx_duration']def __init__(self, flow_el):'''! The initializer.@param self The object pointer.@param flow_el The element.'''self.flowId = int(flow_el.get('flowId'))rxPackets = float(flow_el.get('rxPackets'))txPackets = float(flow_el.get('txPackets'))tx_duration = (parse_time_ns (flow_el.get('timeLastTxPacket')) - parse_time_ns(flow_el.get('timeFirstTxPacket')))*1e-9rx_duration = (parse_time_ns (flow_el.get('timeLastRxPacket')) - parse_time_ns(flow_el.get('timeFirstRxPacket')))*1e-9self.rx_duration = rx_durationself.probe_stats_unsorted = []if rxPackets:self.hopCount = float(flow_el.get('timesForwarded')) / rxPackets + 1else:self.hopCount = -1000if rxPackets:self.delayMean = float(flow_el.get('delaySum')[:-2]) / rxPackets * 1e-9self.packetSizeMean = float(flow_el.get('rxBytes')) / rxPacketselse:self.delayMean = Noneself.packetSizeMean = Noneif rx_duration > 0:self.rxBitrate = float(flow_el.get('rxBytes'))*8 / rx_durationelse:self.rxBitrate = Noneif tx_duration > 0:self.txBitrate = float(flow_el.get('txBytes'))*8 / tx_durationelse:self.txBitrate = Nonelost = float(flow_el.get('lostPackets'))#print "rxBytes: %s; txPackets: %s; rxPackets: %s; lostPackets: %s" % (flow_el.get('rxBytes'), txPackets, rxPackets, lost)if rxPackets == 0:self.packetLossRatio = Noneelse:self.packetLossRatio = (lost / (rxPackets + lost))interrupt_hist_elem = flow_el.find("flowInterruptionsHistogram")if interrupt_hist_elem is None:self.flowInterruptionsHistogram = Noneelse:self.flowInterruptionsHistogram = Histogram(interrupt_hist_elem)## ProbeFlowStats
class ProbeFlowStats(object):## class variables## @var probeId#  probe ID## @var packets#  network packets## @var bytes#  bytes## @var delayFromFirstProbe#  delay from first probe## @var __slots_#  class variable list__slots_ = ['probeId', 'packets', 'bytes', 'delayFromFirstProbe']## Simulation
class Simulation(object):## class variables## @var flows#  list of flowsdef __init__(self, simulation_el):'''! The initializer.@param self The object pointer.@param simulation_el The element.'''self.flows = []FlowClassifier_el, = simulation_el.findall("Ipv4FlowClassifier")flow_map = {}for flow_el in simulation_el.findall("FlowStats/Flow"):flow = Flow(flow_el)flow_map[flow.flowId] = flowself.flows.append(flow)for flow_cls in FlowClassifier_el.findall("Flow"):flowId = int(flow_cls.get('flowId'))flow_map[flowId].fiveTuple = FiveTuple(flow_cls)for probe_elem in simulation_el.findall("FlowProbes/FlowProbe"):probeId = int(probe_elem.get('index'))for stats in probe_elem.findall("FlowStats"):flowId = int(stats.get('flowId'))s = ProbeFlowStats()s.packets = int(stats.get('packets'))s.bytes = float(stats.get('bytes'))s.probeId = probeIdif s.packets > 0:s.delayFromFirstProbe =  parse_time_ns(stats.get('delayFromFirstProbeSum')) / float(s.packets)else:s.delayFromFirstProbe = 0flow_map[flowId].probe_stats_unsorted.append(s)def main(argv):file_obj = open(argv[1])print("Reading XML file ", end=" ")sys.stdout.flush()        level = 0sim_list = []for event, elem in ElementTree.iterparse(file_obj, events=("start", "end")):if event == "start":level += 1if event == "end":level -= 1if level == 0 and elem.tag == 'FlowMonitor':sim = Simulation(elem)sim_list.append(sim)elem.clear() # won't need this any moresys.stdout.write(".")sys.stdout.flush()print(" done.")for sim in sim_list:for flow in sim.flows:t = flow.fiveTupleproto = {6: 'TCP', 17: 'UDP'} [t.protocol]print("FlowID: %i (%s %s/%s --> %s/%i)" % \(flow.flowId, proto, t.sourceAddress, t.sourcePort, t.destinationAddress, t.destinationPort))if flow.txBitrate is None:print("\tTX bitrate: None")else:print("\tTX bitrate: %.2f kbit/s" % (flow.txBitrate*1e-3,))if flow.rxBitrate is None:print("\tRX bitrate: None")else:print("\tRX bitrate: %.2f kbit/s" % (flow.rxBitrate*1e-3,))if flow.delayMean is None:print("\tMean Delay: None")else:print("\tMean Delay: %.2f ms" % (flow.delayMean*1e3,))if flow.packetLossRatio is None:print("\tPacket Loss Ratio: None")else:print("\tPacket Loss Ratio: %.2f %%" % (flow.packetLossRatio*100))if __name__ == '__main__':main(sys.argv)

处理xml

如我用协议AODV的话 Port就是 654

还有一个例子,模拟业务流量的时候用的是端口9,这里 Port 9是服务器端口,客户端和服务器之间的区分在于 客户端是请求应用的发起者,然后服务器朝着客户端发送data(实际的业务payload)信息。(当然客户端也会向服务端发些信息这都没有问题)

用flowmonitor中的不同端口统计业务信息(用户数据)和路由控制信息(路由开销)

从上面的分析可以知道,OLSR,AODV的协议包走的端口如 698/654,而应用数据的端口为9.这里就可以区分网络层的数据包和
协议开销包了。如这里所示:

flowId = “2”的流, 服务器端口是9,客户端向远方服务器9端口发起,目的端口就是9,从上面的关键图可以看出,客户端sourceAddress 10.1.1.11 从本地的 49153端口, 向服务器destination的10.1.1.1的 9端口发送走,UDP(17)协议。

flowId = “557”的流,是客户端sourceAddress 10.1.1.11 从本地的 654 端口, 向中间节点的10.1.1.2的 654端口(AODV协议) ,通过 UDP(17) 进行路由交互,如路由建立路由发现等。

明白了这一点处理xml文件就可以根据不同端口号区分所发送的信息是 data还是控制message,是UDP还是TCP。加上端口判断即可,这里大家可自行修改 flowmon-parse-results.py。以进行更加可信的分析。

数据业务端口配置注意用户socket配置的是9端口。

RoutingExperiment::RoutingExperiment (): port (9),····
}
····
Ptr<Socket>
RoutingExperiment::SetupPacketReceive (Ipv4Address addr, Ptr<Node> node)
{TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");Ptr<Socket> sink = Socket::CreateSocket (node, tid);InetSocketAddress local = InetSocketAddress (addr, port);sink->Bind (local);sink->SetRecvCallback (MakeCallback (&RoutingExperiment::ReceivePacket, this));return sink;
}············Ipv4AddressHelper addressAdhoc;addressAdhoc.SetBase ("10.1.1.0", "255.255.255.0");Ipv4InterfaceContainer adhocInterfaces;adhocInterfaces = addressAdhoc.Assign (adhocDevices);OnOffHelper onoff1 ("ns3::UdpSocketFactory",Address ());onoff1.SetAttribute ("OnTime", StringValue ("ns3::ConstantRandomVariable[Constant=1.0]"));onoff1.SetAttribute ("OffTime", StringValue ("ns3::ConstantRandomVariable[Constant=0.0]"));for (int i = 0; i < nSinks; i++){Ptr<Socket> sink = SetupPacketReceive (adhocInterfaces.GetAddress (i), adhocNodes.Get (i));AddressValue remoteAddress (InetSocketAddress (adhocInterfaces.GetAddress (i), port));onoff1.SetAttribute ("Remote", remoteAddress);Ptr<UniformRandomVariable> var = CreateObject<UniformRandomVariable> ();ApplicationContainer temp = onoff1.Install (adhocNodes.Get (i + nSinks));temp.Start (Seconds (var->GetValue (100.0,101.0)));temp.Stop (Seconds (TotalTime));}

参考文件

[FlowMonitor] G. Carneiro, P. Fortuna, and M. Ricardo. 2009. FlowMonitor: a network monitoring framework for the network simulator 3 (NS-3). In Proceedings of the Fourth International ICST Conference on Performance Evaluation Methodologies and Tools (VALUETOOLS '09).

NS3:FlowMonitor设计讲解相关推荐

  1. 大一c语言课程设计答辩ppt,c语言课程设计讲解内容图文.ppt

    c语言课程设计讲解内容图文 一.课程设计的目的与要求 1.教学目的 本课程设计是学生学习完<C语言程序设计>课程后,进行的一次全面的综合训练,通过课程设计,更好地掌握使用C语言进行程序设计 ...

  2. 钣金cad插件_ug,CAD,SolidWorks,钣金??????非标等设计讲解

    ug,CAD,SolidWorks,钣金​‌‌​‌‌非标等设计讲解 <培训课程> 一.UG.PROE三维产品设计班 1)产品设计流程: 2)三维造型.各类产品结构设计 3)产品表面处理工艺 ...

  3. 【工控老马】电气控制与PLC技术之生产流水线小车控制程序课程设计讲解

    电气控制与PLC技术之生产流水线小车控制程序课程设计讲解 一.设计的基本要求 可编程控制器生产流水线小车控制程序设计要求: 控制要求: 某生产线要求小车执行以下控制: 初始状态下,小车停在行程开关ST ...

  4. 【C#+SQL Server】实现模仿QQ的交友软件 四:主窗体设计讲解(附源码和资源)

    需要源码和资源请点赞关注收藏后评论区留言私信~~~ 其他几个部分文章链接如下 [C#+SQL Server]实现模仿QQ的交友软件 一:系统简介.功能展示与数据库设计(附源码和资源) [C#+SQL ...

  5. 【C#+SQL Server】实现模仿QQ的交友软件 三:申请账号窗体设计讲解(附源码和资源)

    需要源码和资源请点赞关注收藏后评论区留言私信~~~ 其他几个部分文章链接如下 [C#+SQL Server]实现模仿QQ的交友软件 一:系统简介.功能展示与数据库设计(附源码和资源) [C#+SQL ...

  6. 【C#+SQL Server】实现模仿QQ的交友软件 五:聊天窗体设计讲解(附源码和资源)

    需要源码和资源请 点赞关注收藏后评论区留言私信~~~ 其他几个部分文章链接如下 [C#+SQL Server]实现模仿QQ的交友软件 一:系统简介.功能展示与数据库设计(附源码和资源) [C#+SQL ...

  7. mysql表设计讲解_MySQL中数据库的设计归纳讲解

    谈到MySQL中数据库的设计,相信大家都知道这是实现实际业务的重要一步,因此对于Java学习者来说,深入了解和学习数据库的设计是十分有必要的.本文为大家准备了一份MySQL中数据库的设计归纳讲解,内容 ...

  8. yang模型中rpc_领域驱动模型(DDD)设计讲解

    一. 什么是领域驱动模型(DDD)? 领域驱动模型一种设计思想,我们又称为DDD设计思想.是一种为了解决传统设计思想带来的维护困难,沟通困难和交互困难而产生的一种新的思想.也解决了在部分公司中,一个项 ...

  9. 树芯计划-ASIC数字IC设计讲解(1)连载中......

    大家好,我是IC修真院的Andy老师,今天我们一起来学习ASIC数字前端设计课程,在讲课程之前,我们首先来看一些基本的知识点. 那目前来看无论是ASIC设计还是SOC的设计,基本的都是TOP down ...

  10. 进阶项目(6)LCD12864液晶屏幕设计讲解

     写在前面的话 液晶(LCD)显示具有功耗低.体积小.重量轻.超薄等许多其他显示器无法比拟的优点,近几年被广泛应用于FPGA控制的智能仪器.仪表和低功耗的电子产品中.LCD可分为段位式LCD.字符式L ...

最新文章

  1. Python基础数据类型之set集合
  2. rust(34)-Rust and WebAssembly(2)
  3. 安卓个人信息界面_LOL手游上架,安卓+IOS安装教程
  4. 黑白棋子的移动(东方化改题+???)
  5. 完全平方数—leetcode279
  6. UVA 12108 Extraordinarily Tired Students
  7. 以Blog.Core的方式来打开Abp.vNext
  8. wince中重启网卡
  9. 拳王虚拟项目公社:闲鱼知乎引流售卖虚拟资源的虚拟副业项目实操
  10. 项目开发周期与数据库设计对比
  11. python怎么修改默认路径_Python小知识之JupyterLab默认启动路径修改
  12. 在学校报名了计算机一级考试时间,2020年山东计算机一级报名及考试时间
  13. 电脑联想小新连上蓝牙耳机依然外放,终于解决了
  14. Azure:云平台概述
  15. 刘强东「复出」搞团购,京东急什么?
  16. VBS 对IBM Notes的常规操作
  17. 论文-Knowledge Graph Grounded Goal Planning for Open-Domain Conversation Generation
  18. linux char大小,Linux基本数据类型大小——int,char,long int,long long int
  19. MySQL必知必会pdf
  20. Android登陆demo:界面设计及业务代码———Android菜鸟的成长日记

热门文章

  1. 发家致富:爬取双色球信息并统计
  2. 日语输入法和键盘不匹配、微软日语输入法键盘错乱怎么办
  3. Visual Studio爆炸! -VS2010 SP1 * BETA *已发布,上下文
  4. 复现贪吃蛇程序——玩家控制小蛇的移动(第三部分)
  5. java获取时分秒毫秒_JAVA中如何获取毫秒和微秒数
  6. 了解一下DDD领域驱动设计
  7. amaze ui教程
  8. javaScript实现百度换肤案例
  9. [精简整理]疏通中国历史脉络——“元、明、清(1840鸦片战争止)”篇
  10. varchar与varchar2区别