资讯详情

虚拟机和宿主机通过socket通信【C4】

关键词:随机森林,SDN,网络流量 环境:VMware Workstation Pro ,pycharm64,py3,mininet,ryu,ubuntu,linux,wireShark

文章目录

  • 场景一:虚拟机和宿主机通过socket通信,传送packet_in消息
    • 指令步骤
  • 场景二:h访问视频网站,tcpdump抓包并分析
    • 刚才一切都不动
    • mininet-开启h1独立窗口
  • 场景3:抓取视频流和下载流,训练机器学习模型
    • 数据集
      • 数据可视化
    • 训练模型
    • 验证模型的正确性
  • 代码部分
    • 虚拟机-topo-代码
    • 虚拟机-客户端-代码
    • 宿主机-服务端-代码-服务端-代码
    • 随机森林训练-代码训练-代码训练
    • 随机森林验证-代码验证-代码验证
  • 总结

场景一:虚拟机和宿主机通过socket通信,传送packet_in消息

指令步骤

1.运营服务端 在这里插入图片描述 2.运行客户端

ryu-manager C4client.py 

3.启动拓扑文件 此时可以看到客户端的解释packetin数据包信息

场景二:h访问视频网站,tcpdump抓包并分析

刚才一切都不动

mininet-开启h1独立窗口

将127.0.0.53改为8.8.8.保存后关闭

切换用户

su  【用户名】 

访问谷歌浏览器

google-chrom 

打开bilibili,点击视频 bilibili 所用为UDP协议,验证成功

场景3:抓取视频流和下载流,训练机器学习模型

数据集

使用wireShark抓包,选择特征值,保存为.csv文件

数据可视化

预览数据览数据分布范围和异常值

训练模型

模型训练后保存为.pk1文件

验证模型的正确性

简单输出预测结果。

代码部分

虚拟机-topo-代码

位置:mininet/mininet/examples CCCTopo.py 此topo已开启交换机网桥,交换机可以直接访问互联网

#!/usr/bin/python import re import sys from mininet.cli import CLI from mininet.log import setLogLevel, info, error from mininet.net import Mininet from mininet.link import Intf from mininet.topolib import TreeTopo from mininet.util import quietRun from mininet.node import OVSSwitch, OVSController, Controller, RemoteController from mininet.topo import Topo class MyTopo( Topo ): # "this topo is used for Scheme_1"          def __init__( self ):         "Create custom topo."           # Initialize topology         Topo.__init__( self )           # Add hosts          h1 span class="token operator">= self.addHost( 'h1' , ip="10.0.0.1/24", mac="00:00:00:00:00:01", defaultRoute="via 10.0.0.254")
        h2 = self.addHost( 'h2' , ip="10.0.0.2/24", mac="00:00:00:00:00:02", defaultRoute="via 10.0.0.254")
        h3 = self.addHost( 'h3' , ip="10.0.0.3/24", mac="00:00:00:00:00:03", defaultRoute="via 10.0.0.254")
        h4 = self.addHost( 'h4' , ip="10.0.0.4/24", mac="00:00:00:00:00:04", defaultRoute="via 10.0.0.254")
        
        # Add switches
        s1 = self.addSwitch( 's1' )
        s2 = self.addSwitch( 's2' )
        s3 = self.addSwitch( 's3' )
 
        # Add links
        self.addLink( s1, s2 )
        self.addLink( s1, s3 )
        self.addLink( s2, h1 )
        self.addLink( s2, h2 )
        self.addLink( s3, h3 )
        self.addLink( s3, h4 )
  # 
def checkIntf( intf ):
    "Make sure intf exists and is not configured."
    if ( ' %s:' % intf ) not in quietRun( 'ip link show' ):
        error( 'Error:', intf, 'does not exist!\n' )
        exit( 1 )
    ips = re.findall( r'\d+\.\d+\.\d+\.\d+', quietRun( 'ifconfig ' + intf ) )
    if ips:
        error( 'Error:', intf, 'has an IP address,'
               'and is probably in use!\n' )
        exit( 1 )
 
if __name__ == '__main__':
    setLogLevel( 'info' )
 
    # try to get hw intf from the command line; by default, use eth1
    intfName = sys.argv[ 1 ] if len( sys.argv ) > 1 else 'ens38'
    info( '*** Connecting to hw intf: %s' % intfName )
 
    info( '*** Checking', intfName, '\n' )
    checkIntf( intfName )
 
    info( '*** Creating network\n' )
    net = Mininet( topo=MyTopo(),controller=None) 
    #
    switch = net.switches[ 0 ] # 
    info( '*** Adding hardware interface', intfName, 'to switch', switch.name, '\n' )
    _intf = Intf( intfName, node=switch )
     # 
 
    info( '*** Note: you may need to reconfigure the interfaces for '
          'the Mininet hosts:\n', net.hosts, '\n' )
    c0 = RemoteController( 'c0', ip='127.0.0.1', port=6653 )  # 
    net.addController(c0)
    net.start()
    CLI( net )
    net.stop()
topos = { 
        'mytopo':(lambda:MyTopo())}

虚拟机-客户端-代码

位置:ryu/ryu/app C4client.py

from operator import attrgetter
from ryu.app import simple_switch_13
from ryu.controller import ofp_event
from ryu.controller.handler import MAIN_DISPATCHER, DEAD_DISPATCHER, CONFIG_DISPATCHER
from ryu.controller.handler import set_ev_cls
import array
from ryu.lib import hub
from ryu.lib.packet import packet
from ryu.base import app_manager
from ryu.ofproto import ofproto_v1_3
from ryu.controller.handler import MAIN_DISPATCHER
from ctypes.wintypes import BYTE
import socket


class MyMonitor13(simple_switch_13.SimpleSwitch13, app_manager.RyuApp):
    OFP_VERSIONS = [ofproto_v1_3.OFP_VERSION]

    def __init__(self, *args, **kwargs):  # 初始化函数
        super(MyMonitor13, self).__init__(*args, **kwargs)
        self.dp_id = '0'
        self.in_port = '0'

        # 开启client,并连接server
        self.client1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        dst_host = '192.168.203.1'
        dst_port = 12306

        # 防止server端连接不上影响hub的使用
        try:
            self.client1.connect((dst_host, dst_port))
        except Exception as error:
            print('Connect error:', error)

    def doflow(self, datapath, command, priority, match, actions):
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser
        inst = [ofp_parser.OFPInstructionActions(ofp.OFPIT_APPLY_ACTIONS, actions)]
        req = ofp_parser.OFPFlowMod(datapath=datapath, command=command,
                                    priority=priority, match=match, instructions=inst)
        datapath.send_msg(req)

    # 控制器和交换机握手时,向交换机下发默认流表项
    @set_ev_cls(ofp_event.EventOFPSwitchFeatures, CONFIG_DISPATCHER)
    def switch_features_handler(self, ev):
        msg = ev.msg
        datapath = msg.datapath
        ofp = datapath.ofproto
        ofp_parser = datapath.ofproto_parser

        # add table-miss
        command = ofp.OFPFC_ADD
        match = ofp_parser.OFPMatch()
        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_CONTROLLER, ofp.OFPCML_NO_BUFFER)]
        self.doflow(datapath, command, 0, match, actions)

    @set_ev_cls(ofp_event.EventOFPPacketIn, MAIN_DISPATCHER)
    def packet_in_handler(self, ev):
        msg = ev.msg
        dp = msg.datapath
        ofp = dp.ofproto
        ofp_parser = dp.ofproto_parser
        self.dp_id = dp.id

        # 计算出in_port
        start = str(msg).index('oxm_fields') + 11
        end = str(msg).index('),reason')
        inport_str = str(msg)[start:end]
        instr = eval(inport_str)
        self.in_port = instr['in_port']

        actions = [ofp_parser.OFPActionOutput(ofp.OFPP_FLOOD)]

        data = None
        if msg.buffer_id == ofp.OFP_NO_BUFFER:
            data = msg.data
        print('id:{0} in_port:{1}'.format(self.dp_id, self.in_port))
        # 每次有信息经过交换机时,控制器就将获取的dpid和port发送给server
        # info = str(self.dp_id) + ',' + str(self.in_port)

        pkt = packet.Packet(array.array('B', msg.data))
        # 几种协议
        plist = []
        for p in pkt.protocols:
            print('received protocol data:', p)
            plist.append(p)

        info = str(len(data)) + ',' + str(self.in_port) 
        self.client1.send(info.encode())

        out = ofp_parser.OFPPacketOut(
            datapath=dp, buffer_id=msg.buffer_id, in_port=self.in_port,
            actions=actions, data=data)
        dp.send_msg(out)

宿主机-服务端-代码

server.py host为宿主机IP地址 可通过cmd指令ipconfig查询,本机为192.168.203.1

import socket
import re


def main():
    server1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # TCP

    host = '192.168.203.1'
    port = 12306
    server1.bind((host, port))
    print('server lunching . . . ')
    server1.listen(5)
    while True:
        conn, addr = server1.accept()
        print("----------------------------")
        print("Success connect from ", addr)
        try:
            count = 0
            while True:
                data = conn.recv(1024)
                data = re.split(r'[, :]', data.decode('utf-8'))  # 对收到的信息进行解析,包括dpid和port
                count += 1
                print("from {0}:length={1}, in_port={2}".format(addr, data[0], data[1]))
            conn.close()
        except Exception as error:  # 当控制器和应用层断开连接后,输出统计信息
            print('共接收{}条信息。'.format(count - 1))
            print(error)
            exit()


if __name__ == '__main__':
    main()

随机森林-训练-代码

import joblib
import pandas as pd
from sklearn.metrics import accuracy_score, classification_report
from sklearn.preprocessing import StandardScaler
import matplotlib as mpl
import warnings
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.datasets import make_blobs
from sklearn.ensemble import ExtraTreesClassifier, RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier, export_graphviz
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split

# 读取数据
data = pd.read_csv('D:/data.csv')
print(data.head())
# 数据可视化
# 直方图
data.hist()
plt.show()
# 密度图
data.plot(kind='density', subplots=True, layout=(3, 3), sharex=False)
plt.show()
# 箱线图
data.plot(kind='box', subplots=True, layout=(3, 3), sharex=False)
plt.show()
# 相关矩阵图
correlations = data.corr()
fig = plt.figure()
ax = fig.add_subplot(111)
cax = ax.matshow(correlations, vmin=-1, vmax=1)
fig.colorbar(cax)  # 颜色柱
ticks = np.arange(0, 9, 1)
plt.show()
# 散点矩阵图
pd.plotting.scatter_matrix(data)
plt.show()

# 提取自变量和因变量
X = data.iloc[:, :-1].values
y = data.iloc[:, -1].values
# 实现标准化
scaler = StandardScaler()  # 实例化
scaler.fit(X)
print('查看每列均值的属性mean_:', scaler.mean_)  # 查看每列均值的属性mean_
print('查看每列方差属性var_:', scaler.var_)  # 查看每列方差属性var_
x = scaler.transform(X)
# train_test_split方法:将样本集合划分为训练集和测试集
random_state = 1  # 随机数种子
test_size = 0.2  # 若在0~1之间,为测试集样本数目与原始样本数目之比;若为整数,则是测试集样本的数目
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=random_state, test_size=test_size)
# print('x_train:', x_train)
print('x_test:', x_test)
# print('y_train:', y_train)
# print('y_test:', y_test)
# 随机森林分类类RandomForestClassifier
n_estimators = 100  # 森林中决策树的数目
max_features = 0.4  # 寻找最佳分割时需要考虑的特征数目(百分比)
max_dep = 10  # 决策树的最大深度
min_samples_split = 2  # 分割内部节点所需要的最小样本数量
bootstrap = True  # 建立决策树时,是否使用有放回抽样
clf = RandomForestClassifier(n_estimators=n_estimators, max_features=max_features, max_depth=max_dep,
                             min_samples_split=min_samples_split, bootstrap=bootstrap)
# 交叉检验
estimator = clf  # 估计器,也就是模型
verbose = 2  # 日志冗长度:int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出
scores2 = cross_val_score(estimator, x_train, y_train, cv=10, verbose=verbose)
print('交叉检验得分:', scores2)
print('RandomForestClassifier交叉验证准确率为:%.4f' % scores2.mean())

# 预测数据集
clf.fit(x_train, y_train)
y_p = clf.predict(x_test)
print('预测值:', y_p)
print('准确率:', accuracy_score(y_test, y_p))
print("其他指标:\n", classification_report(y_test, y_p, target_names=['0', '1']))

joblib.dump(clf, 'D:/C4_RF.pk1')

随机森林-验证-代码

# 提取自变量和因变量
import joblib
from sklearn.preprocessing import StandardScaler

# X = [1099.78, 679, 699.7, 54, ]
X = [[948.69, 106, 112.7, 54, 1466, 647.711, 3.149191, 4.21835],
     [960.16, 255, 266.4, 54, 1466, 670.822, 0.03011, 0.003753],
     [1038.46, 3238, 3118.2, 54, 1506, 678.776, 0.000721, 0.00032],
     [995.66, 2202, 2212, 54, 1506, 692.776, 0.000993, 0.000452]]
# 实现标准化
scaler = StandardScaler()  # 实例化
scaler.fit(X)
x = scaler.transform(X)
estimator = joblib.load("D:/C4_RF.pk1")
y_predict = estimator.predict(x)
print('检测结果为:', y_predict)

总结

原计划: 1.离线状态下训练随机森林算法,生成分类识别模型 2.利用ryu控制器自定义客户端文件获取h1上网时流量的各项特征值 3.传送到服务端,显示分类结果 遇到的问题与反思: 1.原计划中随机森林训练已完成,socket通信已完成 2.h1上网已实现 3.h1上网时能成功采集packetin消息并解析 4.解析packetin数据包后发现并不是我们想要的h1浏览视频得到的下载数据包!!! 5.摆烂 6.发现利用tcpdump可以抓取数据包,也是我们想要的 7.统计特征值后发现mininet自动将分割开的数据包合成一个,与我们wireshark抓取的形态不一样!!! 8.摆烂 9.直接在外部宿主机抓包并统计,验证结果良好符合预期 10.赶紧结束,提交作品 11.以上遇到的问题留到以后再解决吧~~

标签: pk1接近传感器sc1204

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台