说明:
控制器:pox betta版 ubuntu
组播程序:multicastv_8_9sw.py
需要修改的地方:
1:1906 2046行,交换机设定值是9,即要有九个交换机,多少个交换机这个值设定为多少。在def run2():函数里面和虚拟主机相连的交换机不能超过9个,且端口都接到4号端口。
2:1960行,监控流量的交换机的dpid,监控哪个写哪个
3:2010,2030等行自适应的机器10.0.0.60对应的mac地址要根据不同的机器改
4:1926 ,1968,2039行,sleep时间可以改变,即多少秒计算一次流量
Media server : ubuntu
发送程序:server.c h264.h multith8.py send_videolist_mediatomanage.py
需要修改的地方:
h264.h:
1: 29行 修改目的ip为10.0.0.50,目的端口都是49270
Server.c:
1:748行,修改发送视频源,da38.264视频为960x540,发送效果最好,空间可伸缩
2:1214, 1375行,修改sleep时间,不同视频时间不一样,da38.264都是4000,dayi.264为7000和8000
multith8.py:
1:166 ,404行,将mac值改为本机即为媒体服务器的mac
2:118,128,135行,将mac改为10.0.0.50对应机器的mac
send_videolist_mediatomanage.py:
1:29行,修改目录路径
客户端:ubuntu
接收程序:qclient
需要注意的地方:
1:安装g++,进入live文件夹,执行./genMakefiles linux,之后将文件夹拷到/usr/local/lib/中。
2:安装mplayer,./configure –enable-svc , make , sudo make install
客户端:windows
接收程序:qclient
需要注意的地方:
1:安装qt5,一直下一步, qt-opensource-windows-x86-msvc2010_opengl-5.3.1.exe 之后根据环境变量.txt修改环境变量:
2:将msvcp100d.dll,msvcr100d.dll复制到system32和syswow中
3:将MinGW拷到c盘,重新编译一遍或者在环境变量里面修改路径为lab3的都可以
Ostinato:ubuntu
需要注意的地方:
1:ip和mac地址千万不能写错,不然开启ostinato的时候交换机会挂掉
2:工作模式就是顺着视频流的方向
3:对于双网卡的机器,每个网卡都要对应一个固定的ip,不然重启交换机后两个网卡容易都是一个ip,这样启动控制器程序后会有问题
主要工作流程:
1,客户端向设备管理器请求视频:
def sendplay():
global serverIp ,pulse ,GID,FID
print "beginnnnnnnnnnnnnnnnn"
if pulse == 1:
print "pulse is iiiiiiiiiiiiiiiiiiiiiiiiiii"
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port=50972
s.connect((serverIp,port))
client = 1
s.send(str(GID)+'#'+str(FID)+'#'+getHwAddr('eth0')+'#'+(s.getsockname()[0])+'#'+str(client))
s.recv(1024)
s.close()
time.sleep(1)
thread.start_new_thread(mrun, (getHwAddr('eth0'),))
time.sleep(1000)
发送的内容包括请求的视频组GID,层数FID,自身mac地址和套接字自身地址(ipaddr,port)。
2,设备管理器接受并处理消息:
(1)设备管理器接受info消息
str(GID)+’#’+str(FID)+’#’+getHwAddr(‘eth0’)+’#’+(s.getsockname()[0])
class clientToserver(threading.Thread): #客户端到服务器 服务器侦听端口消息,等待客户端发信息,接受info消息str(GID)+'#'+str(FID)+'#'+getHwAddr('eth0')+'#'+(s.getsockname()[0])
def __init__(self):
threading.Thread.__init__(self)
self.thread_stop=False
def run(self):
while True:
global info,con
if con.acquire(): #获得锁
print 'thread clienttoserver'
print info
self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port=50972
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
self.socket.bind((self.socket.getsockname()[0],port))
self.socket.listen(100)
if info is None:
connection,address=self.socket.accept()
info=connection.recv(1024)
self.socket.close()
print info
con.release() #释放锁
time.sleep(0.1)
def stop(self):
self.thread_stop=True
(2)处理info消息并发送给控制器:
处理思想如下:
dic[GID][FID]=[(mac1,ip1),(mac2,ip2)]
dicp[GID][FID]=port #GID表示视频组,FID表示请求视频层数
host [mac]=GID
mactoip [mac]=ip
info=str[GID]#str[FID]#mac#ip
inf=info.split('#') #通过指定分隔符对字符串进行切片
gid = int(inf[0])
fid = int(inf[1])
mac=inf[2]
ip=inf[3]
一,该mac请求过视频(mac in host.keys()):
【1】和原来请求视频不同(gid is not G):删除之前客户端的所在的视频组和层数信息,从新分配
(1)如果客户端所请求的视频在之前的dic里(G in dic.keys()):
<1>层数相同(i in dic[G].keys()): 将mac ip添加到dic字典里: dic[G][i].append((mac,ip))
<2>层数之前没有: 添加mac ip到新的dic : dic[G][i]=[(mac,ip)]
(2)如果客户端所请求的视频不在之前的视频组dic里:加入 dic[G][i]=[(mac,ip)]
【2】 请求的还是原来的视频(gid is G):
<1> n > fid,新请求的视频层数没有原来的高,删除指定流
<2>n < fid, 新请求的视频层数比原来的高,加入指定流
二,该客户端的mac地址不在host{}里,即该客户端第一次请求视频:
【1】如果客户端所请求的视频在之前的视频组里(G in dic.keys()):
<1>层数相同(i in dic[G].keys()): 将mac ip添加到dic字典里: dic[G][i].append((mac,ip))
<2>层数之前没有: 添加mac ip到新的dic : dic[G][i]=[(mac,ip)]
【2】如果客户端所请求的视频不在之前的视频组里: 加入 dic[G][i]=[(mac,ip)]
同时将新信息发送给控制器:
self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port=8001
self.s1.connect(('10.0.0.200',port))
self.s1.send('i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i]))
self.s1.close()
info信息如下:
‘i’+’#’+str(G)+str(i)+’#’+mac+’#’+ip+’#’+a+’#’+(self.s1.getsockname())[0]+’#’+str(dicp[G][i])
其中 a为媒体服务器的mac 。
3,控制器接受并处理消息:
(1)def run() 接受处理消息:
接收到的info信息如下:
‘i’+’#’+str(G)+str(i)+’#’+mac+’#’+ip+’#’+a+’#’+(self.s1.getsockname())[0]+’#’+str(dicp[G][i])处理得到:
groupid = str(G)+str(i)
host = (mac,ip)
source = (a,self.s1.getsockname())[0])
port = string.atoi(str(dicp[G][i])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
port = 8001
s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
s.bind(('10.0.0.200',port))
s.listen(100)
connection, address = s.accept()
info = connection.recv(1024)
information = info.split('#')
if information[0] == 'b':
groupid = information[1]
host = (information[2], information[3])
source = (information[4], information[5])
port = string.atoi(information[6])
globle_sourcegroup[groupid] = (source[0], source[1], port)
core.l2_multi.raiseEvent(MulticastInstall,groupid,source,host,port)
if information[0] == 'i':
groupid = information[1]
host = (information[2], information[3])
source = (information[4], information[5])
port = string.atoi(information[6])
core.l2_multi.raiseEvent(MulticastInsert,groupid,source,host,port,)
if information[0] == 'd':
groupid = information[1]
host = (information[2], information[3])
source = (information[4], information[5])
port = string.atoi(information[6])
core.l2_multi.raiseEvent(MulticastDelete,groupid,source,host,port,)
connection.close()
(2)事件管理系统过程:
1,首先建立事件类:
PathInstalled,Switch,MulticastInstall,MulticastInsert,MulticastDelete。定义上述事件:
class PathInstalled (Event):
"""
Fired when a path is installed
"""
def __init__ (self, path):
Event.__init__(self)
self.path = path
class MulticastInstall(Event):
def __init__(self,groupid,source,host,port):
Event.__init__(self)
self.groupid = groupid
self.source = source
self.host = host
self.port = port
class MulticastInsert(Event):
def __init__(self,groupid,source,host,port):
Event.__init__(self)
self.groupid = groupid
self.source = source
self.host = host
self.port = port
class MulticastDelete(Event):
def __init__(self,groupid,source,host,port):
Event.__init__(self)
self.groupid = groupid
self.source = source
self.host = host
self.port = port
2,将定义好的事件注册到pox.core里,让pox知道这是个事件。创建raise事件的类,继承自EventMixin:
class l2_multi (EventMixin):
_eventMixin_events = set([
PathInstalled,
MulticastInstall,
MulticastInsert,
MulticastDelete,
])
在最后的 def launch ()中的 core.registerNew(l2_multi) 注册组件。
3,创建处理事件的函数:
自动设置Listeners,处理函数有:
(1)def _handle_MulticastInstall(self,event):
(2)def _handle_MulticastInsert(self,event):
(3)def _handle_MulticastDelete(self,event):
class handlemulticast(object):
def __init__(self):
core.l2_multi.addListeners(self)
def _handle_MulticastInstall(self,event):
print 'handle multicastinstall'
if event.groupid in globle_idgroup.keys():
return
else:
src = (EthAddr(event.source[0]),IPAddr(event.source[1]))
hst = {}
hst[EthAddr(event.host[0])] = IPAddr(event.host[1])
src_port = event.port
print hst
globle_idgroup[event.groupid] = multicast(src,hst,src_port)
globle_idgroup[event.groupid].multicast_install()
def _handle_MulticastInsert(self,event):
print 'handle multicastinsert'
if event.groupid not in globle_idgroup.keys():
return
else:
hostmac = EthAddr(event.host[0])
hostip = IPAddr(event.host[1])
globle_idgroup[event.groupid].multicast_insert(hostmac,hostip)
def _handle_MulticastDelete(self,event):
print 'handle multicastdelete'
if event.groupid not in globle_idgroup.keys():
return
else:
hostmac = EthAddr(event.host[0])
globle_idgroup[event.groupid].multicast_delete(hostmac)
if globle_idgroup[event.groupid].router_table == {}:
del globle_idgroup[event.groupid]
del globle_sourcegroup[event.groupid]
4,raise事件,触发事件:
即def run()中的以下语句:
core.l2_multi.raiseEvent(MulticastInstall,groupid,source,host,port)
...
core.l2_multi.raiseEvent(MulticastInsert,groupid,source,host,port,)
...
core.l2_multi.raiseEvent(MulticastDelate,groupid,source,host,port,)
当达到某个条件后,开始触发MulticastInstall事件,并将参数传入,之后调用处理函数。
5,最后注册组件:
def launch ():
core.registerNew(l2_multi)
core.register()指定一个对象; core.registerNew( )指定一个类.
(3)事件处理函数:
上述第三步 class handlemulticast(object) 中的处理函数主体:
def _handle_MulticastInstall(self,event):
src = (EthAddr(event.source[0]),IPAddr(event.source[1]))
hst[EthAddr(event.host[0])] = IPAddr(event.host[1])
src_port = event.port
globle_idgroup[event.groupid] = multicast(src,hst,src_port)
globle_idgroup[event.groupid].multicast_install()
def _handle_MulticastInsert(self,event):
hostmac = EthAddr(event.host[0])
hostip = IPAddr(event.host[1])
globle_idgroup[event.groupid].multicast_insert(hostmac,hostip)
def _handle_MulticastDelete(self,event):
hostmac = EthAddr(event.host[0])
globle_idgroup[event.groupid].multicast_delete(hostmac)
分别调用class multicast(object)中的
multicast_install(),multicast_insert(hostmac,hostip),multicast_delete(hostmac)函数下发流表。
其中初始化过程如下:
def __init__(self, src = None, hst = {}, src_port = 0):
self.source = src #(sourcemac,sourceip)
self.multicast_host = hst #{hostmac:hostip}
self.source_port = src_port
self.inswitch = mac_map[src[0]][0] #mac_map[mac]=(sw,port)
self.inport = mac_map[src[0]][1]
self.router_table = {}#{switch object:[(inport,outport)]}
可见,只需通过sourcemac和hostmac就能得到相连sw和port,通过
path = _get_path(sw1, sw2, firstport, finalport) 方法建立路径,之后下发流表。