基于SDN的SVC视频组播系统搭建二

Media server : ubuntu
发送程序:server.c h264.h multith8.py send_videolist_mediatomanage.py

服务器端(send_videolist_mediatomanage.py )

服务器向设备管理器发送目录视频列表:

#!/usr/bin/env python2
#-*-encoding:utf-8-*-
import os,sys,socket
manageip = '10.0.0.111'  #需要设置管理服务器ip
def send_videolist(dir):
    list = os.listdir(dir)  #列出目录下的所有文件和目录
    print list
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40000
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)#这里value设置为1,表示将SO_REUSEADDR标记为TRUE,操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。
    s1.connect((manageip,port)) #连接管理服务器ip
    s1.send(str(list))  #list是一个列表,不能被send,要转换为str或buf才行
    s1.close()
dir = '/home/liuxun/file/'
send_videolist(dir)


客户端(multith8.py )

接收设备服务器发来的视频列表字符串,并将其简要转换为列表:

def recv_videolistbuf():   #接收设备服务器发来的视频列表字符串,并将其简要转换为列表
    global aa
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40006 
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    s1.bind((s1.getsockname()[0],port))  #绑定自身即client的ip
    s1.listen(5) 
    send_hostip()
    connection,address=s1.accept()
    video_num = 0
    buf = connection.recv(1024)  #buf为字符串,要转换为列表
    print buf
    c = buf.strip('[')  #将字符串的左边[删去
    b = c.strip(']')     #将字符串的右边]删去
    aa = b.split(',')     #将字符串以 , 为界限转换成列表  
    s1.close()


请求视频,发送请求的视频组GID,层数FID,自身ip和mac:

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))
        #pr4nt self.hwAddr
    client = 1
        s.send(str(GID)+'#'+str(FID)+'#'+getHwAddr('eth0')+'#'+(s.getsockname()[0])+'#'+str(client))
         #s.send(str(GID)+'#'+str(FID)+'#'+'00:00:00:00:00:11'+'#'+'11.11.11.1')

        s.recv(1024)
        s.close()  
        time.sleep(1)

        #os.system("mplayer sdp://'/home/openflow/桌面/264.sdp'")   
        thread.start_new_thread(mrun, (getHwAddr('eth0'),))
        #thread.start_new_thread(run, ('00:00:00:00:00:11',))
        #thread.start_new_thread(play,())
        time.sleep(1000)



设备管理器(multith8.py )

设备管理器接受来自服务器的视频列表(port = 40000),接受客户端ip并发送视频列表给客户端 (port = 40004)。处理info消息(GID,FID,mac,ip)后发送给控制器。

代码分析:

(1)设备管理器接受来自服务器的视频列表:

def recv_videolist():    #接收来自media server的视频列表 
    global m_list   
    video_num = 0
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40000
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 
    s1.bind((s1.getsockname()[0],port))  #绑定管理服务器本身的ip
    s1.listen(100)        
    connection,address=s1.accept() #调用accept方法时,socket会进入'waiting'(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有俩个元素的元组,形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客户通信;第二个元素(address)是客户的internet地址。
    m_list = connection.recv(1024)   #服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受数据时会进入'blocket'状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接受端。以后调用recv时,多余的数据会从缓冲区删除。
    print m_list #此时接受到的m_list为字符串['dayi720p2.264', 'fast720p.txt', 'multith.py', 'dayi720p1.264', 'final.264', 'a.264', 'da2.264', 'a1.264', 'fast720p.txt~', 'out.264', 'dayi720p5.264', 'h264.h'],不是列表
    s1.close()

(2)接受客户端ip并发送视频列表给客户端:

def listen_client():   #接收客户端发来的客户端的ip 并发送视频列表
    while 1:
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40004  #侦听client请求
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    s1.bind((s1.getsockname()[0],port))  #绑定自身即manage的ip
    s1.listen(100) 
    connection,address=s1.accept()
    serverip = connection.recv(1024)
    print serverip
    send_videolist(serverip)
    s1.close()
    thread.exit_thread()

def send_videolist(serverip):   #向客户端发送视频列表
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40006
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    print '#####################################'
    print serverip
    print m_list
    s.connect((serverip,port))  #连接客户端ip
    s.send(m_list)  #list是一个列表,不能被send,要转换为str或buf才行 
    s.close()

(3)客户端到服务器: 服务器侦听端口消息,等待客户端发信息,接受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

(4)服务器到控制器,对相关信息进行处理

说明:

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)]

代码如下:

class serverTocontroller(threading.Thread):     #服务器到控制器           
    def __init__(self):
        threading.Thread.__init__(self)
        self.thread_stop=False          

    def run(self):
        global a
        a='30:0E:D5:C1:6B:5A'
        while True:
            global info,con
            if con.acquire():
                    print "server to controller"
                    if info is None:
                        print 'Waiting the messenger from client...'
                    else:
                        inf=info.split('#') #通过指定分隔符对字符串进行切片
                        mac=inf[2]
                        ip=inf[3] 
                        fid = int(inf[1])
                        gid = int(inf[0])
                        if mac in host.keys():  #mac为字典host的键值,如果客户端之前就在host里,则删除之前客户端的所在的视频组和层数信息,从新分配
                            G=host[mac]         #G为这个键对应的value
                            print '该客户端的mac地址已经在host{}里存在'
                            if gid is not G:
                                print 'gid is not G'
                                for i in dic[G].keys():
                                    print 'dic###################'
                                    print dic
                                    if (mac, ip) in dic[G][i]:
                                            dic[G][i].remove((mac, ip))    #??????????
                                            print 'dic###################'
                                            print dic
                                            self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=8001
                                            self.s1.connect(('10.0.0.200',port))
                                            self.s1.send('d'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i]))
                                            print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid不一样,删除'
                                            print 'd'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                            if dic[G][i] == []:
                                                del dic[G][i]
                                            if dic[G].keys() is None:
                                                del dic[G]
                                            time.sleep(0.5)
                                G=int(inf[0])
                                FID=inf[1]
                                host[mac]=G
                                mactoip[mac] = ip
                                if G in dic.keys():   #G为视频组,如果客户端所请求的视频在之前的视频组里
                                    for i in range(int(FID)+1):  #层数
                                        if i in dic[G].keys():
                                            dic[G][i].append((mac,ip))  #将新的client的mac ip加入到dic字典里
                                            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]))

                                            print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                        else:
                                            dic[G][i]=[(mac,ip)]  #如果客户端所请求的层数之前没有,则加入一个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]))

                                            print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                        time.sleep(0.5)
                                else:  #如果客户端所请求的视频不在之前的视频组里
                                    for i in range(int(FID)+1):
                                        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]))

                                        print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                        self.s1.close()
                                        time.sleep(0.5)  

                            else:   #if gid is G:请求的还是原来的视频
                                    print 'gid is G 000000000000000000'
                                    n=0 
                                    for i in dic[G].keys():
                                            if (mac, ip) in dic[G][i]:
                                            n=n+1
                                    n=n-1
                                    print '之前客户端所播放的层数,在dic字典里该视频对应的keys'
                                    print n

                                        if n > fid:
                                            delayer = n-fid
                                            print 'delayer^^^^^^^^^^^^^^^^'
                                            print delayer

                                            self.s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=9001
                                            self.s.connect((ip,port))
                                            self.s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
                                            self.s.send('L'+str(delayer))
                                            time.sleep(8)

                                            for j in range(0,delayer):
                                                dic[G][n-j].remove((mac, ip))
                                                self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                                port=8001
                                                self.s1.connect(('10.0.0.200',port))
                                                print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid一样,新请求的视频层数没有原来的高,删除指定流'
                                                self.s1.send('d'+'#'+str(G)+str(n-j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n-j]))
                                                print 'd'+'#'+str(G)+str(n-j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n-j])
                                                if dic[G][n-j] == []:
                                                    del dic[G][n-j]
                                                if dic[G].keys() is None:
                                                    del dic[G]
                                            print 'request fid less than origin fid(n) : n > fid , deleted dic'         
                                            print dic

                                        if n < fid:
                                            delayer = fid-n
                                            print 'insertlayer^^^^^^^^^^^^^^^^'
                                            print delayer

                                            self.s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=9001
                                            self.s.connect((ip,port))
                                            self.s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
                                            self.s.send('B'+str(delayer))
                                            time.sleep(8)

                                            for j in range(1,delayer+1):    
                                                self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                                port=8001
                                                if i in dic[G].keys():
                                                    dic[G][n+j].append((mac,ip))
                                                else:
                                                    dic[G][n+j]=[(mac,ip)]
                                                self.s1.connect(('10.0.0.200',port))
                                                print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid一样,新请求的视频层数比原来的高,加入指定流'
                                                self.s1.send('i'+'#'+str(G)+str(n+j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n+j]))
                                                print 'i'+'#'+str(G)+str(n+j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n+j])
                                            print 'request fid more than origin fid(n) : n < fid , added dic'        
                                            print dic


#                                        if n == fid:
#                                            continue


                            info = None
                            con.release()
                            time.sleep(0.1)                 
                            continue   #重新while循环  

                        print '该客户端的mac地址不在host{}里,即该客户端第一次请求视频'    
                        G=int(inf[0])
                        FID=inf[1]
                        host[mac]=G
                        mactoip[mac] = ip
                        if G in dic.keys():   #G为视频组
                            for i in range(int(FID)+1):  #层数
                                if i in dic[G].keys():
                                    dic[G][i].append((mac,ip))  #将新的client的mac ip加入到dic字典里
                                    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]))
                                    print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                    self.s1.close()
                                else:
                                    dic[G][i]=[(mac,ip)]  #如果客户端所请求的层数之前没有,则加入一个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]))
                                    print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                    self.s1.close()
                                time.sleep(0.5)
                        else:  #如果客户端所请求的视频不在之前的视频组里
                            for i in range(int(FID)+1):
                                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]))
                                print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                self.s1.close()
                                time.sleep(0.5)
                    info = None

                    print "dic******************************"
                    print dic
                    print "dicp*****************************"
                    print dicp
                    print "host*****************************"
                    print host
                    #con.notify()
                    #con.wait()
                    con.release()
                    time.sleep(0.1)


    def stop(self):
            self.thread_stop=True

(5)心跳机制,防止客户端不正常退出

class receving(threading.Thread):   #接受客户端mac地址
    def __init__(self):

        threading.Thread.__init__(self)
        self.thread_stop=False
    def run(self):
        print "recevingggggggggggggggggggggggggggg"
        while True:
            self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)    
            port=7874
            self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  
            self.socket.bind((self.socket.getsockname()[0],port))
            self.socket.listen(100)
            connection,address=self.socket.accept()
            buf=connection.recv(1024)  #客户端mac
#            connection.close()
        self.socket.close()
            global timer
            print 'buffffffffffffffffffffffff'
            print buf
            timer[buf]=time.time()
            #print "receiving timer"
            #print timer
#            self.socket.close()

    def stop(self):
            self.thread_stop=True

class heartbeat(threading.Thread):  #向控制器发送信息,防止客户端不正常退出,管理服务器对其进行的处理
    def __init__(self):
        threading.Thread.__init__(self)
        self.thread_stop=False



    def run(self):

        global a
        a='30:0E:D5:C1:6B:5A'
        while True:
            t1=time.time()
            global timer


            for i in timer.keys():
                t2=t1-timer[i]
#                print '%%%%%%%%%%%%%%%%%%%%%%%%%%%'
#                print t2
#                print '%%%%%%%%%%%%%%%%%%%%%%%%%%%'
                if t2>24:
                    print 'The host whose mac is %s has lost' %(i)
                    Gid=host[i]
                    ip=mactoip[i]
                    for f in dic[Gid].keys():
                        if (i,ip) in dic[Gid][f]:
                            self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                            port=8001
                            self.s1.connect(('10.0.0.200',port))
                            self.s1.send('d'+'#'+str(Gid)+str(f)+'#'+i+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[Gid][f]))
                            print 'd'+'#'+str(Gid)+str(f)+'#'+i+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[Gid][f])
                            self.s1.close()
                            dic[Gid][f].remove((i, ip))
                            if dic[Gid][f] == []:
                                del dic[Gid][f]
                            if dic[Gid].keys() is None:
                                del dic[Gid]    
                    del host[i]
                    del mactoip[i]
                    del timer[i]  



完整代码:

#!/usr/bin/env python2
#-*-encoding:utf-8-*-
import socket
import time
import os
import sys
import thread
import struct
import threading
import select
from collections import defaultdict

info=None
dic=defaultdict(lambda:defaultdict(lambda:[None]))#dic [GID][FID]=[(mac1,ip1),(mac2,ip2)] 
dicp=defaultdict(lambda:defaultdict(lambda:None)) #dic [GID][FID]=port
host={}                                           #dic [mac]=GID 
mactoip={}                                        #dic [mac]=ip
timer={}                                          #dic [mac]=time.time()          
con=threading.Condition()

dicp[0][0]=50002
dicp[0][1]=50003
dicp[0][2]=50004

controllerip = '10.0.0.200'

def recv_videolist():    #接收来自media server的视频列表
    global m_list   
    video_num = 0
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40000
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) 
        s1.bind((s1.getsockname()[0],port))  #绑定管理服务器本身的ip
        s1.listen(100) 
    connection,address=s1.accept()
    m_list = connection.recv(1024)  #此时接受到的list为字符串['dayi720p2.264', 'fast720p.txt', 'multith.py', 'dayi720p1.264', 'final.264', 'a.264', 'da2.264', 'a1.264', 'fast720p.txt~', 'out.264', 'dayi720p5.264', 'h264.h'],不是列表
    print m_list
    s1.close()

def listen_client():   #接收客户端发来的客户端的ip 并发送视频列表
    while 1:
    s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40004  #侦听client请求
    s1.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        s1.bind((s1.getsockname()[0],port))  #绑定自身即manage的ip
        s1.listen(100) 
    connection,address=s1.accept()
    serverip = connection.recv(1024)
    print serverip
    send_videolist(serverip)
    s1.close()
    thread.exit_thread()

def send_videolist(serverip):   #向客户端发送视频列表
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port = 40006
    s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
    print '#####################################'
    print serverip
    print m_list
    s.connect((serverip,port))  #连接客户端ip
    s.send(m_list)  #list是一个列表,不能被send,要转换为str或buf才行 
    s.close()

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)  #这里value设置为1,表示将SO_REUSEADDR标记为TRUE,操作系统会在服务器socket被关闭或服务器进程终止后马上释放该服务器的端口,否则操作系统会保留几分钟该端口。
                self.socket.bind((self.socket.getsockname()[0],port))  
                self.socket.listen(100)  #利用listen()函数进行侦听连接。该函数只有一个参数,其指明了在服务器实际处理连接的时候,允许有多少个未决(等待)的连接在队列中等待。作为一个约定,很多人设置为5。如:s.listen(5)
                if info is None:
                    connection,address=self.socket.accept()  #调用accept方法时,socket会进入'waiting'(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。accept方法返回一个含有俩个元素的元组,形如(connection,address)。第一个元素(connection)是新的socket对象,服务器通过它与客户通信;第二个元素(address)是客户的internet地址。
                    info=connection.recv(1024) #服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。recv方法在接受数据时会进入'blocket'状态,最后返回一个字符串,用它来表示收到的数据。如果发送的量超过recv所允许,数据会被截断。多余的数据将缓冲于接受端。以后调用recv时,多余的数据会从缓冲区删除。

#                    connection.close() #传输结束,服务器调用socket的close方法以关闭连接
            self.socket.close()
                    print info
                    #con.notify()
                #con.wait()
                con.release() #释放锁
#       self.socket.close()
                time.sleep(0.1)

    def stop(self):
            self.thread_stop=True


class sertocon(threading.Thread):  #虚拟主机  发送虚拟主机的ip mac以及请求的视频和层数给控制器
  def __init__(self):
    threading.Thread.__init__(self)
    self.thread_stop=False

  def run(self):
    a='30:0E:D5:C1:6B:5A'

    info = {}
#    for i in range(1, 5):
#      info[i] = "0#" + "2#" + "00:00:00:00:11:0" + str(i) + "#" + "10.0.0.10" + str(i)
#    for i in range(5,10):
#      info[i] = "0#" + "1#" + "00:00:00:00:11:0" + str(i) + "#" + "10.0.0.10" + str(i)
    for i in range(1, 10):  #对于主机1-20分配ip和mac地址以及请求的视频和层数
      info[i] = "0#" + "0#" + "00:00:00:00:11:0" + str(i) + "#" + "10.0.0.10" + str(i)
    for i in range(10, 21):  #对于主机1-20分配ip和mac地址以及请求的视频和层数
      info[i] = "0#" + "0#" + "00:00:00:00:11:" + str(i) + "#" + "10.0.0.1" + str(i)
    self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port=8001
    self.s1.connect(('10.0.0.200',port))   #connect连接控制器
    self.s1.send('b'+'#'+'00'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][0]))  #socket对象的getpeername()和getsockname()方法都返回包含一个IP地址和端口的二元组(这个二元组的形式就像你传递给connect和bind的)。getpeername返回所连接的远程socket的地址和端口,getsockname返回关于本地socket的相同信息。 
    print 'b'+'#'+'00'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][0])
    print '8001===========00'
    self.s1.close()
    time.sleep(5)
    print '8001===========11'
    self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port=8001
    self.s1.connect(('10.0.0.200',port))
    print '8001===========22'
    self.s1.send('b'+'#'+'01'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][1]))
    print 'b'+'#'+'01'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][1])
    self.s1.close()
    time.sleep(3)
    self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    port=8001
    self.s1.connect(('10.0.0.200',port))
    self.s1.send('b'+'#'+'02'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][2]))
    print 'b'+'#'+'02'+'#'+'30:0E:D5:C1:6A:96'+'#'+'10.0.0.50'+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[0][2])
    self.s1.close()
    time.sleep(3)

    for i in range(2, 4):
      inf = info[i].split('#')  #字符串的split函数默认分隔符是空格 ' ',这里为#,功能把字符串拆成列表
      gid = int(inf[0])  #请求视频类型
      fid = int(inf[1])  #视频层数0 1 2
      mac=inf[2]
      ip=inf[3]
      for j in range(0,fid+1):
        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(gid)+str(j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[gid][j]))
        print 'i'+'#'+str(gid)+str(j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[gid][j])
        self.s1.close()
        time.sleep(3)

    def stop(self):
      self.thread_stop=True

class serverTocontroller(threading.Thread):     #服务器到控制器           
    def __init__(self):
        threading.Thread.__init__(self)
        self.thread_stop=False          

    def run(self):
        global a
        a='30:0E:D5:C1:6B:5A'
        while True:
            global info,con
            if con.acquire():
                    print "server to controller"
                    if info is None:
                        print 'Waiting the messenger from client...'
                    else:
                        inf=info.split('#')
                        mac=inf[2]
                        ip=inf[3] 
                        fid = int(inf[1])
                        gid = int(inf[0])
                        if mac in host.keys():  #mac为字典host的键值,如果客户端之前就在host里,则删除之前客户端的所在的视频组和层数信息,从新分配
                            G=host[mac]         #G为这个键对应的value
                            print '该客户端的mac地址已经在host{}里存在'
#                          if int(inf[4]) is 0:  #控制器发来的自适应信息
                            if gid is not G:
                                print 'gid is not G'
                                for i in dic[G].keys():
                                    print 'dic###################'
                                    print dic
                                    if (mac, ip) in dic[G][i]:
                                            dic[G][i].remove((mac, ip))    #??????????
                                            print 'dic###################'
                                            print dic
                                            self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=8001
                                            self.s1.connect(('10.0.0.200',port))
                                            self.s1.send('d'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i]))
                                            print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid不一样,删除'
                                            print 'd'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                            if dic[G][i] == []:
                                                del dic[G][i]
                                            if dic[G].keys() is None:
                                                del dic[G]
                                            time.sleep(0.5)
                                G=int(inf[0])
                                FID=inf[1]
                                host[mac]=G
                                mactoip[mac] = ip
                                if G in dic.keys():   #G为视频组
                                    for i in range(int(FID)+1):  #层数
                                        if i in dic[G].keys():
                                            dic[G][i].append((mac,ip))  #将新的client的mac ip加入到dic字典里
                                            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]))

                                            print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                        else:
                                            dic[G][i]=[(mac,ip)]  #如果客户端所请求的层数之前没有,则加入一个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]))

                                            print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                            self.s1.close()
                                        time.sleep(0.5)
                                else:  #如果客户端所请求的视频不再之前的视频组里
                                    for i in range(int(FID)+1):
                                        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]))

                                        print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                        self.s1.close()
                                        time.sleep(0.5)  

                            else:   #if gid is G:请求的还是原来的视频
                                    print 'gid is G 000000000000000000'
                                    n=0 
                                    for i in dic[G].keys():
                                            if (mac, ip) in dic[G][i]:
                                            n=n+1
                                    n=n-1
                                    print '之前客户端所播放的层数,在dic字典里该视频对应的keys'
                                    print n
#                                for i in dic[G].keys():    
#                                    if (mac, ip) in dic[G][i]:
                                        if n > fid:
                                            delayer = n-fid
                                            print 'delayer^^^^^^^^^^^^^^^^'
                                            print delayer

                                            self.s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=9001
                                            self.s.connect((ip,port))
                                            self.s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
                                            self.s.send('L'+str(delayer))
                                            time.sleep(8)

                                            for j in range(0,delayer):
                                                dic[G][n-j].remove((mac, ip))
                                                self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                                port=8001
                                                self.s1.connect(('10.0.0.200',port))
                                                print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid一样,新请求的视频层数没有原来的高,删除指定流'
                                                self.s1.send('d'+'#'+str(G)+str(n-j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n-j]))
                                                print 'd'+'#'+str(G)+str(n-j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n-j])
                                                if dic[G][n-j] == []:
                                                    del dic[G][n-j]
                                                if dic[G].keys() is None:
                                                    del dic[G]
                                            print 'request fid less than origin fid(n) : n > fid , deleted dic'         
                                            print dic

                                        if n < fid:
                                            delayer = fid-n
                                            print 'insertlayer^^^^^^^^^^^^^^^^'
                                            print delayer

                                            self.s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                            port=9001
                                            self.s.connect((ip,port))
                                            self.s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
                                            self.s.send('B'+str(delayer))
                                            time.sleep(8)

                                            for j in range(1,delayer+1):    
                                                self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                                                port=8001
                                                if i in dic[G].keys():
                                                    dic[G][n+j].append((mac,ip))
                                                else:
                                                    dic[G][n+j]=[(mac,ip)]
                                                self.s1.connect(('10.0.0.200',port))
                                                print '新发送的mac在原来的host里,请求的gid和原来mac对应的gid一样,新请求的视频层数比原来的高,加入指定流'
                                                self.s1.send('i'+'#'+str(G)+str(n+j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n+j]))
                                                print 'i'+'#'+str(G)+str(n+j)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][n+j])
                                            print 'request fid more than origin fid(n) : n < fid , added dic'        
                                            print dic


#                                        if n == fid:
#                                            continue


                            info = None
                            con.release()
                            time.sleep(0.1)                 
                            continue   #重新while循环  

                        print '该客户端的mac地址不在host{}里,即该客户端第一次请求视频'    
                        G=int(inf[0])
                        FID=inf[1]
                        host[mac]=G
                        mactoip[mac] = ip
                        if G in dic.keys():   #G为视频组
                            for i in range(int(FID)+1):  #层数
                                if i in dic[G].keys():
                                    dic[G][i].append((mac,ip))  #将新的client的mac ip加入到dic字典里
                                    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]))
                                    print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                    self.s1.close()
                                else:
                                    dic[G][i]=[(mac,ip)]  #如果客户端所请求的层数之前没有,则加入一个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]))
                                    print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                    self.s1.close()
                                time.sleep(0.5)
                        else:  #如果客户端所请求的视频不在之前的视频组里
                            for i in range(int(FID)+1):
                                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]))
                                print 'i'+'#'+str(G)+str(i)+'#'+mac+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[G][i])
                                self.s1.close()
                                time.sleep(0.5)
                    info = None

                    print "dic******************************"
                    print dic
                    print "dicp*****************************"
                    print dicp
                    print "host*****************************"
                    print host
                    #con.notify()
                    #con.wait()
                    con.release()
                    time.sleep(0.1)


    def stop(self):
            self.thread_stop=True

class receving(threading.Thread):   #接受客户端mac地址
    def __init__(self):

        threading.Thread.__init__(self)
        self.thread_stop=False
    def run(self):
        print "recevingggggggggggggggggggggggggggg"
        while True:
            self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)    
            port=7874
            self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)  
            self.socket.bind((self.socket.getsockname()[0],port))
            self.socket.listen(100)
            connection,address=self.socket.accept()
            buf=connection.recv(1024)  #客户端mac
#            connection.close()
        self.socket.close()
            global timer
            print 'buffffffffffffffffffffffff'
            print buf
            timer[buf]=time.time()
            #print "receiving timer"
            #print timer
#            self.socket.close()

    def stop(self):
            self.thread_stop=True

class heartbeat(threading.Thread):  #向控制器发送信息,防止客户端不正常退出,管理服务器对其进行的处理
    def __init__(self):
        threading.Thread.__init__(self)
        self.thread_stop=False



    def run(self):

        global a
        a='30:0E:D5:C1:6B:5A'
        while True:
            t1=time.time()
            global timer


            for i in timer.keys():
                t2=t1-timer[i]
#                print '%%%%%%%%%%%%%%%%%%%%%%%%%%%'
#                print t2
#                print '%%%%%%%%%%%%%%%%%%%%%%%%%%%'
                if t2>24:
                    print 'The host whose mac is %s has lost' %(i)
                    Gid=host[i]
                    ip=mactoip[i]
                    for f in dic[Gid].keys():
                        if (i,ip) in dic[Gid][f]:
                            self.s1=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
                            port=8001
                            self.s1.connect(('10.0.0.200',port))
                            self.s1.send('d'+'#'+str(Gid)+str(f)+'#'+i+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[Gid][f]))
                            print 'd'+'#'+str(Gid)+str(f)+'#'+i+'#'+ip+'#'+a+'#'+(self.s1.getsockname())[0]+'#'+str(dicp[Gid][f])
                            self.s1.close()
                            dic[Gid][f].remove((i, ip))
                            if dic[Gid][f] == []:
                                del dic[Gid][f]
                            if dic[Gid].keys() is None:
                                del dic[Gid]    
                    del host[i]
                    del mactoip[i]
                    del timer[i]    
                """     
                print 'mactoip'
                print mactoip
                print 'timer'
                print timer
                """

def test():
    thread.start_new_thread(recv_videolist,())
    thread.start_new_thread(listen_client,())
#    recv_videolist()
#    listen_client()
    thread0=heartbeat()
    thread0.start()
    thread1=clientToserver()
    thread1.start() 
    thread2 = sertocon()
    thread2.start()
    thread3=serverTocontroller()
    thread3.start()
    thread4=receving()
    thread4.start()

    time.sleep(1000)

if __name__=='__main__':
    test()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值