• mininet实验 动态改变转发规则实验


    写在前面


    本实验参考

    • POX脚本设置好控制器的转发策略,所以只要理解脚本。
    • mininet脚本设置好拓扑和相关信息,所以也只要理解脚本。
    • POX脚本目前基本看不懂。
    • 本实验我学会了:POX控制器Web界面,第一次真正的看到了流表项。

    实验拓扑


    image

    • 在该环境下,假设H1 ping H4,初始的路由规则是S1-S2-S5,一秒后,路由转发规则变为S1-S3-S5,再过一秒,规则变为S1-S4-S5,然后再回到最初的转发规则S1-S2-S5。通过这个循环调度的例子动态地改变交换机的转发规则。

    实验步骤


    1.搭建环境

    • 安装了mininet的虚拟机。
    • 安装了pox的虚拟机。

    2.创建脚本

    • /pox目录下新建文件lab_controller.py,编辑其内容:
    from pox.core import core
    
    import pox.openflow.libopenflow_01 as of
    
    from pox.lib.util import dpidToStr
    
    from pox.lib.addresses import IPAddr, EthAddr
    
    from pox.lib.packet.arp import arp
    
    from pox.lib.packet.ethernet import ethernet, ETHER_BROADCAST
    
    from pox.lib.packet.packet_base import packet_base
    
    from pox.lib.packet.packet_utils import *
    
    import pox.lib.packet as pkt
    
    from pox.lib.recoco import Timer
    
    import time
    
    
    
    log = core.getLogger()
    
    
    
    s1_dpid=0
    
    s2_dpid=0
    
    s3_dpid=0
    
    s4_dpid=0
    
    s5_dpid=0
    
    
    
    s1_p1=0
    
    s1_p4=0
    
    s1_p5=0
    
    s1_p6=0
    
    s2_p1=0
    
    s3_p1=0
    
    s4_p1=0
    
    
    
    pre_s1_p1=0
    
    pre_s1_p4=0
    
    pre_s1_p5=0
    
    pre_s1_p6=0
    
    pre_s2_p1=0
    
    pre_s3_p1=0
    
    pre_s4_p1=0
    
    
    
    turn=0
    
    
    
    def getTheTime():  #fuction to create a timestamp
    
      flock = time.localtime()
    
      then = "[%s-%s-%s" %(str(flock.tm_year),str(flock.tm_mon),str(flock.tm_mday))
    
    
    
      if int(flock.tm_hour)<10:
    
        hrs = "0%s" % (str(flock.tm_hour))
    
      else:
    
        hrs = str(flock.tm_hour)
    
      if int(flock.tm_min)<10:
    
        mins = str(flock.tm_min)
    
        secs = "0%s" % (str(flock.tm_sec))
    
      else:
    
        secs = str(flock.tm_sec)
    
    
    
      then +="]%s.%s.%s" % (hrs,mins,secs)
    
      return then
    
    
    
    
    
    def _timer_func ():
    
      global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid,turn
    
    
    
    
    
      #print getTheTime(), "sent the port stats request to s1_dpid"
    
    
    
      if turn==0:
    
          msg = of.ofp_flow_mod()
    
          msg.command=of.OFPFC_MODIFY_STRICT
    
          msg.priority =100
    
          msg.idle_timeout = 0
    
          msg.hard_timeout = 0
    
          msg.match.dl_type = 0x0800
    
          msg.match.nw_dst = "10.0.0.4"
    
          msg.actions.append(of.ofp_action_output(port = 5))
    
          core.openflow.getConnection(s1_dpid).send(msg)
    
          turn=1
    
          return
    
    
    
      if turn==1:
    
          msg = of.ofp_flow_mod()
    
          msg.command=of.OFPFC_MODIFY_STRICT
    
          msg.priority =100
    
          msg.idle_timeout = 0
    
          msg.hard_timeout = 0
    
          msg.match.dl_type = 0x0800
    
          msg.match.nw_dst = "10.0.0.4"
    
          msg.actions.append(of.ofp_action_output(port = 6))
    
          core.openflow.getConnection(s1_dpid).send(msg)
    
          turn=2
    
          return
    
    
    
      if turn==2:
    
          msg = of.ofp_flow_mod()
    
          msg.command=of.OFPFC_MODIFY_STRICT
    
          msg.priority =100
    
          msg.idle_timeout = 0
    
          msg.hard_timeout = 0
    
          msg.match.dl_type = 0x0800
    
          msg.match.nw_dst = "10.0.0.4"
    
          msg.actions.append(of.ofp_action_output(port = 4))
    
          turn=0
    
          return
    
    
    
    def _handle_portstats_received (event):
    
      global s1_p1,s1_p4, s1_p5, s1_p6, s2_p1, s3_p1, s4_p1
    
      global pre_s1_p1,pre_s1_p4, pre_s1_p5, pre_s1_p6, pre_s2_p1, pre_s3_p1, pre_s4_p1
    
    
    
      if event.connection.dpid==s1_dpid:
    
        for f in event.stats:
    
          if int(f.port_no)<65534:
    
            if f.port_no==1:
    
              pre_s1_p1=s1_p1
    
              s1_p1=f.rx_packets
    
    
            if f.port_no==4:
    
              pre_s1_p4=s1_p4
    
              s1_p4=f.tx_packets
    
              #s1_p4=f.tx_bytes
    
    
            if f.port_no==5:
    
              pre_s1_p5=s1_p5
    
              s1_p5=f.tx_packets
    
            if f.port_no==6:
    
              pre_s1_p6=s1_p6
    
              s1_p6=f.tx_packets
    
    
    
         for f in event.stats:
    
           if int(f.port_no)<65534:
    
             if f.port_no==1:
    
               pre_s2_p1=s2_p1
    
               s2_p1=f.rx_packets
    
               #s2_p1=f.rx_bytes
    
    
      if event.connection.dpid==s3_dpid:
    
         for f in event.stats:
    
           if int(f.port_no)<65534:
    
             if f.port_no==1:
    
               pre_s3_p1=s3_p1
    
               s3_p1=f.rx_packets
    
    
    
    
      if event.connection.dpid==s4_dpid:
    
         for f in event.stats:
    
           if int(f.port_no)<65534:
    
             if f.port_no==1:
    
               pre_s4_p1=s4_p1
    
               s4_p1=f.rx_packets
    
    
    
    
    def _handle_ConnectionUp (event):
    
      global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid
    
      print "ConnectionUp: ",dpidToStr(event.connection.dpid)
    
    
    
      #remember the connection dpid for switch
    
      for m in event.connection.features.ports:
    
        if m.name == "s1-eth1":
    
          s1_dpid = event.connection.dpid
    
          print "s1_dpid=", s1_dpid
    
        elif m.name == "s2-eth1":
    
          s2_dpid = event.connection.dpid
    
          print "s2_dpid=", s2_dpid
    
        elif m.name == "s3-eth1":
    
          s3_dpid = event.connection.dpid
    
        elif m.name == "s4-eth1":
    
          s4_dpid = event.connection.dpid
    
          print "s4_dpid=", s4_dpid
    
        elif m.name == "s5-eth1":
    
          s5_dpid = event.connection.dpid
    
          print "s5_dpid=", s5_dpid
    
    
    
      if s1_dpid<>0 and s2_dpid<>0 and s3_dpid<>0 and s4_dpid<>0:
    
        Timer(1, _timer_func, recurring=True)
    
    
    
    def _handle_PacketIn(event):
    
      global s1_dpid, s2_dpid, s3_dpid, s4_dpid, s5_dpid
    
    
    
      packet=event.parsed
    
    
    
    
      if event.connection.dpid==s1_dpid:
    
         a=packet.find('arp')
    
         if a and a.protodst=="10.0.0.4":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=4))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.5":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=5))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.6":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=6))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.1":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=1))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.2":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=2))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.3":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=3))
    
           event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.1"
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.2"
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.3"
    
         msg.actions.append(of.ofp_action_output(port = 3))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 1
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.4"
    
         msg.actions.append(of.ofp_action_output(port = 4))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.5"
    
         msg.actions.append(of.ofp_action_output(port = 5))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.6"
    
         msg.actions.append(of.ofp_action_output(port = 6))
    
         event.connection.send(msg)
    
    
    
      elif event.connection.dpid==s2_dpid:
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
      elif event.connection.dpid==s3_dpid:
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
      elif event.connection.dpid==s4_dpid:
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 1
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0806
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =10
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.in_port = 2
    
         msg.match.dl_type=0x0800
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
      elif event.connection.dpid==s5_dpid:
    
         a=packet.find('arp')
    
         if a and a.protodst=="10.0.0.4":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=4))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.5":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=5))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.6":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=6))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.1":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=1))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.2":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=2))
    
           event.connection.send(msg)
    
    
    
         if a and a.protodst=="10.0.0.3":
    
           msg = of.ofp_packet_out(data=event.ofp)
    
           msg.actions.append(of.ofp_action_output(port=3))
    
           event.connection.send(msg)
    
    
    
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.1"
    
         msg.actions.append(of.ofp_action_output(port = 1))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.2"
    
         msg.actions.append(of.ofp_action_output(port = 2))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.3"
    
         msg.actions.append(of.ofp_action_output(port = 3))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.4"
    
         msg.actions.append(of.ofp_action_output(port = 4))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.5"
    
         msg.actions.append(of.ofp_action_output(port = 5))
    
         event.connection.send(msg)
    
    
    
         msg = of.ofp_flow_mod()
    
         msg.priority =100
    
         msg.idle_timeout = 0
    
         msg.hard_timeout = 0
    
         msg.match.dl_type = 0x0800
    
         msg.match.nw_dst = "10.0.0.6"
    
         msg.actions.append(of.ofp_action_output(port = 6))
    
         event.connection.send(msg)
    
    
    
    def launch ():
    
      global start_time
    
      core.openflow.addListenerByName("PortStatsReceived",_handle_portstats_received)
    
      core.openflow.addListenerByName("ConnectionUp", _handle_ConnectionUp)
    
      core.openflow.addListenerByName("PacketIn",_handle_PacketIn)
    
    • 该脚本实现了动态转发策略。
    • 我猜测基本思想应该是,基于时间来给交换机s1下发流表项。
    • 在Mininet中创建文件mymininet.py。编辑其内容为:
    #!/usr/bin/python
    
     
    
    from mininet.topo import Topo
    
    from mininet.net import Mininet
    
    from mininet.node import CPULimitedHost
    
    from mininet.link import TCLink
    
    from mininet.util import dumpNodeConnections
    
    from mininet.log import setLogLevel
    
    from mininet.node import Controller 
    
    from mininet.cli import CLI
    
    from functools import partial
    
    from mininet.node import RemoteController
    
    import os
    
     
    
     
    
    class MyTopo(Topo):
    
        "Single switch connected to n hosts."
    
        def __init__(self):
    
            Topo.__init__(self)
    
            s1=self.addSwitch('s1')
    
            s2=self.addSwitch('s2')
    
            s3=self.addSwitch('s3')
    
            s4=self.addSwitch('s4')
    
            s5=self.addSwitch('s5') 
    
            h1=self.addHost('h1')
    
            h2=self.addHost('h2')
    
            h3=self.addHost('h3')
    
            h4=self.addHost('h4')
    
            h5=self.addHost('h5')
    
            h6=self.addHost('h6')
    
             
    
            self.addLink(h1, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)
    
            self.addLink(h2, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(h3, s1, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)
    
            self.addLink(s1, s2, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s1, s3, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s1, s4, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s2, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s3, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True)  
    
            self.addLink(s4, s5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s5, h4, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s5, h5, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
            self.addLink(s5, h6, bw=1, delay='10ms', loss=0, max_queue_size=1000, use_htb=True) 
    
     
    
    def perfTest():
    
        "Create network and run simple performance test"
    
        topo = MyTopo()
    
    
        net = Mininet(topo=topo, host=CPULimitedHost, link=TCLink, controller=partial(RemoteController, ip='10.0.0.13', port=6633))
    
        net.start()
    
        print "Dumping host connections"
    
        dumpNodeConnections(net.hosts)
    
        h1,h2,h3=net.get('h1','h2','h3')
    
        h4,h5,h6=net.get('h4','h5','h6')
    
        h1.setMAC("0:0:0:0:0:1")
    
        h2.setMAC("0:0:0:0:0:2")
    
        h3.setMAC("0:0:0:0:0:3")
    
        h4.setMAC("0:0:0:0:0:4")
    
        h5.setMAC("0:0:0:0:0:5")
    
        h6.setMAC("0:0:0:0:0:6")
    
        CLI(net)
    
        net.stop()
    
     
    
    if __name__ == '__main__':
    
        setLogLevel('info')
    
        perfTest()
    
    • 该脚本设置了拓扑。基本可以理解。

    3.运行脚本

    • /pox目录下运行脚本lab_controller.py
    ./pox.py lab_controller
    
    • 在Mininet下运行脚本mymininet.py
    chmod +x mymininet.py
    ./mymininet.py
    
    • mininet终端信息

    • POX控制器终端信息

    • 现在我们通过h1向h4发包,来检测动态转发功能。
    • 在mininet终端输入:
    h1 ping -i 0.1 h4 #h1每秒向h4发10个包
    

    • 这时在POX界面并没有出现有用的信息,反而是一些warning信息。

    4.解决方案

    • 既然在终端中没法看到发送的细节,我想到了Web界面。别的控制器都有UI界面POX也应该有吧?
    • 我在一篇博客中找到了POX UI界面的实现方式:Poxdesk。

    参考博客

    • 运行POX脚本时要想使用poxdesk必须多加一些参数,对于本实验运行lab_controller.py时,命令如下:
    ./pox.py lab_controller web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk
    
    • 通用命令:
    ./pox.py 要运行的脚本 web messenger messenger.log_service messenger.ajax_transport openflow.of_service poxdesk
    
    • 浏览器中输入:http://pox-ip:8000/poxdesk 来访问界面,其中pox-ip是本机IP地址。
    • 进入Web界面后,我们打开s1的flowtable窗口。可以发现:对于目的是10.0.0.4(主机h4)的流表项在周期性变化,action中output端口在5,6之间切换。但是没有4(交换机s2),这个问题没有解决,可能是脚本本身的问题。

    5.具体的连接图

    • 通过mininet中的net命令可以得拓扑的详细信息,我简单的画了个示意图便于理解:

    存在问题


    • 端口切换时,为什么不能切换到s2?
  • 相关阅读:
    C#实现注册码
    多表链接 Left join
    Repeater 一行显示两列数据
    Repeater一行显示数据库中多行表记录
    HP QC(Quality Center)在Windows 7 IE8 IE9下不能工作解决方案
    Android应用换肤总结
    Lua 第一个应用程序 Hello World
    JNI 技术与 Android 应用
    NSAutoreleasePool' is unavailable: not avail
    1-2基础控件
  • 原文地址:https://www.cnblogs.com/031602523liu/p/8995331.html
Copyright © 2020-2023  润新知