感谢csdn网友的热心支持和帮助,现已已经设计好了多对多p2p视频的客户端协议的总体框架,目标是用支持256条流并发接收与发送。这里的流是指视频流,音频流,或文件流。数据分包后,小包的头部的目标是缩到4字节,现在已经设计完毕。现在贴出来供大家参与,并希望各位DirectShow,p2p,多对多同时视频的高手继续热心指点。
struct MSG_HDR_BODY{
  BYTE bytOperation;//操作码
  BYTE bytStreamID;//流ID
  BYTE bytTimeStamp;//时间戳
  BYTE bytOffset;//数据片偏移
}
现在开始设计服务器端协议,我是打算采用一个结构体表示一个客户(包括IP,端口,用户ID,是否在线)。现在的问题是如何其它客户提供一个用户ID(或还有其它辅助数据)就可以得到这个客户的各种信息,以方便p2p。
一种想法是把客户的一些信息(包括用户名,密码,ID以外的信息,比如IP,端口,最后一次UDP心跳包时间)存在数据库里,这样只担心性能问题,怕频繁访问数据库会降低速度。另一种想法是采用多级索引的方法放在内存里,相关的想法还在考虑中,希望高手给点意见哦

解决方案 »

  1.   

    其它的很多资料已经在置顶的 ***如何突破上传速度***里讨论过了,也欢迎大家继续参与
    http://community.csdn.net/Expert/TopicView.asp?id=4428750
      

  2.   

    >>kevinmartin(海魂)  时间:2006-1-5 10:22:00
    继续关注,我最近也在研究这方面的内容,不过对楼主的这些想法有一点不敢赞同哦。
    =================
    感谢你的意见,能具体说说吗?你有QQ和E-mail没有,我想和具体聊聊
    我的E-mail:[email protected]
      

  3.   

    你好,首先恭喜你完成了成果!!我目前也再弄相关的视频的研究,只不过是刚刚起步,很多东西都不懂,比如,如何用VC作一个视频软件,如何采集到摄像头的信息等等!!真心的希望能得到你的帮助!!!E-mail:[email protected]
      

  4.   

    现在的问题是如何其它客户提供一个用户ID(或还有其它辅助数据)就可以得到这个客户的各种信息,以方便p2p。
    一种想法是把客户的一些信息(包括用户名,密码,ID以外的信息,比如IP,端口,最后一次UDP心跳包时间)存在数据库里,这样只担心性能问题,怕频繁访问数据库会降低速度。另一种想法是采用多级索引的方法放在内存里,相关的想法还在考虑中,希望高手给点意见哦================================>
    建议使用STL的Map将ID和客户的各种信息关联起来,这样用ID查找很快。如果保存的信息量很大的话考虑用Map+多级索引+数据库预读。当然预读的算法需要好好研究一下。
    ^_^ 抛砖引玉……
      

  5.   

    我不赞同BT的方式进行多点视频传输,况且,举行一个视频会议的时候,如果有10方参加,难道每一方的人都要能看到其他9方的视频信息?我经过计算,在176*144的分辨率以15fps大概要占用4k的带宽,如果物理带宽是50k的话,同时进行超过8路,肯定会非常困难的,况且,这里还是不带音频数据的。如果这个50k是bit的话,同时只能进行1路。所以,这种情况下,我比较倾向于在服务器建立n个频道,进入频道的人可以看视频信息,这个视频信息在一个时间只能有一个人使用,所有人都可以看到,这样就是基于服务器转发。控制频道数量,就可以控制服务器负载。同时,我觉得你对协议的数据这么处理感到很不理解。我用等长度的协议,都用unsigned long,也才4个字节,并且能够保证平台兼容性,同样,对每个协议可以考虑使用二级协议,以增强扩展性,即使这样,每个包为了协议是用到的数据量也不会超过20个字节,而每个包的长度是不定的,真正最关键的包是发送视频信息的包,而一个视频信息的包长度怎么也在2k,这么一点用作协议的流量根本算不了什么。同时,我建议在协议中指定包的长度,这样不要用固定长度的发送数据,而到了接收端通过给定的长度去计算是否正确,你可以用10000的缓冲区接受udp包,而recvfrom()返回值是实际接收到的长度。所以,我认为你对协议的考虑是多虑了。
      

  6.   

    我的email是kevinm#dl.cn,也希望能够和您讨论。msn:kevinm#dl.cn,公司一般不用qq注意把#换成@。
      

  7.   

    kevinmartin(海魂):感谢你的留言,感谢你的宝贵的建议。不知你等长协议头用unsinged long是怎么安排的。你的二级协议是指什么。你说的视频信息包长度在2k是指包长度大小定为2K吗?
    你对我的哪一个考虑是认为多虑的呢?我关于多人视频,我考虑的确实比较久,一方面要方便行的通,另一方面又要照顾包头大小。现在我确定的方案是,最多支持256条流,也就是说最多是和256个人视频,不过在实际情况中应该没有这个数。而且一般的屏幕也放不下太多的视频窗口。所以,我可能采用9分屏,或16分屏的做法,这样其实也只有同时和9个人或16个人视频,而不管这个会议室有多少人参与,也就是说,采用有选择性的方法同时只和想要的人视频就可以解决这个问题。
    关于包头大小,我也是考虑了很久的,之所以采用可变包头的方法,是因为一方面尽可能的节省带宽开销,另一方面也是为了加快切换速度,包的意义由头一个字节来定义,这样就最大的满足了我的要求了,而且操作也是可行的。
    关于包长度,因为考虑到性能和网络问题,具体数值还没有确定,目前可能参与512,1024,1400等
    关于视音频,可能是采用可变fps的作法,只让关心的视频流畅,而且主视频窗口会大一点。压缩算法,是采用Windows Media Video 9,和Windows Media voice。
    已经给你发邮件了
      

  8.   

    wangk(倒之) :感谢你的意见,上面是给你的回复,再补充一下。现在我给用户两个ID,一个为永久ID,值唯一,表示用户在数据库里的ID,另一个ID为临时ID,值在同一时刻也是唯一的。用户上线后,分配给其一个临时在线ID,其它用这个临时ID可以快速定位这个用户在内存中的结构体。用户下线后,收回这个临时在线ID,以供其它用户使用。其实这个临时在线ID的值就是两个数组成员ID的组合:)
      

  9.   

    多大带宽可以跑一路音视频?
    据说现在上海一个公司再64k的modem上跑的很好!
      

  10.   

    duangexin521(duangexin):你最近还有新东东吗,呵呵,发到
      

  11.   

    >>taianmonkey  时间:2006-1-6 14:48:00
    多大带宽可以跑一路音视频?
    据说现在上海一个公司再64k的modem上跑的很好!
    =====================
    那只是我的软件的最小要求!
      

  12.   

    好了,现在用户结构仍为32字节,流的结构体占9个字节,节点结构体为17字节(多了一个字节,但很有用)。到这里在理论上已经通过了,下一步是再根据服务器的情况,较验一下客户端的情况,再下一步是,稍微设计一下数据库,再下一步就写DirectShow里的Filter了,希望,一路顺利,也希望大家继续关注,祝各位开心^_^
      

  13.   

    建议LZ研究研究E话通这个软件!
      

  14.   

    框架差不多了,数据库真是easy,现在难在Filter了,如何把Filter和我定义的结构整合起来呢,我会回去再想想的,想好了再发上来,也想看看大家有没有好的点子,周未了,祝大家玩的开心^_^
      

  15.   

    Stefine(C/C++ → VC → C# ,达不到目标不回家过年 ) () 信誉:100  2006 
    ==================
    嗯,蛮好的:)
    我现在想自定义一个Allocator了,不知有什么难度没有,一个流一个Filter,一个GraphBuilder,这样子方便两个流各自为政,互不干扰,另外,使用DirectShow也可以对某个流录像,呵呵,高人指点一下哟
      

  16.   

    谢谢,成形产品可能还要过一段时间,不过框架既将成形了!
    现在正在想法子自定义Allocator,打算NetSenderFilter,和NetReceiverFilter使用自定义的Allocator,发送使用推模式,而接收使用拉模式
      

  17.   

    我不太清楚你现在的情况下以15fps的视频(不包括音频数据),占用的带宽是多少?因为我不太熟悉Windows Media Video 9的压缩情况。不管支持多少路,别说是256路,只要网络带宽支持,1000路都没有问题,关键是,你1路现在需要占用的带宽是多少?你说用户数据是32字节?为什么这么定义?难道每个包就32个字节+4一共36个字节?
    我的建议是在里面增加一个packageSize的字段,unsigned short就行,指定用户数据的长度。所谓二级协议,我举个例子吧。struct stMESSAGE
    {
        unsigned char  iMsgType;
        unsigned short iMsgLen;
        unsigned char  cMsgContent[10000];
    }struct stCHATMESSAGE
    {
        unsigned char iMsgType;
        unsigned short iMsgLen;
        unsigned char  cMsgContent[10000];
    }在中间使用的时候,将包定义为stMESSAGE格式的,当发送的信息是聊天信息的时候,如下使用:
    stMESSAGE msg;
    msg.iMsgType = MSG_CHATMESSAGE;
    stCHATMESSAGE chatMsg;
    chatMsg.iMsgType = MSG_USERCHATMESSAGE;
    chatMsg.iMsgLen = strlen(chatInfo);
    strncpy(chatMsg.cMsgContent, chatInfo, strlen(chatInfo) + 1);
    msg.iMsgLen = chatMsg.iMsgLen + sizeof(chatMsg.iMsgType) + sizeof(chatMsg.iMsgLen);
    memcpy(msg.cMsgContent, &chatMsg, chatMsg.iMsgLen);我建议使用这种变长度的协议,具体长度通过iMsgLen指定,而不是使用固定的32字节,这样对网络的有效使用率太低。
      

  18.   

    哦,这样啊,我想想。
    我指的用户结构32字节是指服务器端存放用户上线后各种状态的一个结构体,和包在网络中发送时使用的协议的头部结构是不搭边的。
    我是参照那个叫做哈夫曼编码的意思,才想出可变包长变度的鬼主意的。
    定义一些包头
    define LOGIN,LOGOFF,MEDIAPACKETstruct LOGIN{
      BYTE      bytOperation;
      CHAR[10]  szUserName
      CHAR[10]  szPassword
    };struct ACK_LOGIN{
      BYTE      bytOperation;
      LONG      lnOnlineID;
      LONG      lnUserID;
      BOOL      bSuccess;
    };
    struct LOGOFF{
      BYTE     bytOperation;
      CHAR[10]  szUserName
      CHAR[10]  szPassword
      LONG      lnOnlineID;
    };struct ACK_LOGOFF{
      BYTE     bytOperation;
      CHAR[10]  szUserName
      CHAR[10]  szPassword
      LONG      lnOnlineID;
      BOOL      bSuccess;    
    }; 你看到了吗?我要登录了 bytOperation=LOGIN,
    我要注消了bytOperation=LOGOFF,等等,各种协议的结构都不一样,是吧,长度随你定后来,我打算加个发字符消息struct TEXTMSG{
      BYTE     bytOperation=SENDTEXT
      LONG     lnUserFrom;
      LONG     lnUserTo;
      LONG     lnTextLenth;
      CHAR[100] szText;
    };
    是吧,我想要结构怎么样,就怎么样,呵呵,
    这些只是一次性的包而已,如果我想发一段一个包发不了的数据,那么,我就把数据分包,包头就这样定义
    struct LARGECHUNK{
     struct LARGECHUNK_HDR{
         BYTE bytOperation=LARGECHUNK;
         LONG lnTotalLenth;
         LONG lnCurentOffset;
     };
     0110101010001100011001.................
    }
    因为协议是你定的,你当然知道LARGECHUNK的结构体是多大,是吧
    当你收到的包的第一个字节是LARGECHUNK的时候,你就使用这个结构体,当你收到的包的头一个字节是LOGIN的时候,你就使用LOGIN结构体是吧.
    之所以还要进行精心设计,是因为要符合一些效率啊,统计学啊,其它因素啊什么的原理
    反正一句话,想怎么设计就怎么设计,想添加就添加,呵呵
    前面我想方设法减少一个结构为4字节,是为什么呀? 因为这种包在流传送中出现的频率太多了,不能太占空间,当然还有对包处理时的性能考虑,什么?你知道了?不就是因为可能就一个long来表示嘛!呵呵,你是知道了,我也是想用一个LONG来表示,但这只是表皮的东东,背后还有一段故事呢,你想听吗,我打算做好后,过一段时间开源算了嘻嘻,新鲜啵~~
      

  19.   

    Yes, u r right, but have you thought of the expansibility?for example, when server send a message to client that someone has sent to server a chat message, every will get the chat message, so, you create a struct called struct CHATMESSAGE, that is alright.tomorrow, server has updated, server will send you a message to show the advisement, and the advisement should be shown as RED, and u should create another struct called struct SYSTEMADMESSAGE, and do the nearly the same as struct CHATMESSAGE, that is alright too.the day after tomorrow, server will be update again, and the server want to send you a system message, it should be shown as GREEN, and you again create a struct called struct SYSTEMMESSAGE, and do the nearly the same as struct CHATMESSAGE and SYSTEMADMESSAGE. is that alright?and some days later.....one years later, you will see that you had defined 一坨 struct, and it is very very hard for you to maintain it...what will do then? restructure your structure in network? then the early version will be expired...... never be used.then do you know, what is expansibility?
      

  20.   

    Good! Thanks for your interesting idea!
    well, everything is all right!
    have your ever heard about something about NIC address solution? it's about why 4bytes of data is choosed to identify Network Interface Card(NIC) unic address id, and 4 bytes as its manufactor's id? the answer is, when they used up the unic address id, they have selld 4G of products! then the company is rich enough to register a new name.
    now look back to our situation, it's just the same as the tale told above.
    moreover, when i used up 1 byte of namespace, i can easily intruduce another byte for the namespace,ie, ff01,ff02,ff03....,right?
    I've newly just discover a english fans:) are you?
      

  21.   

    so when i used up my namesapce, i belive i have the most confince and own enough experience to design a brand new protocal, more powerful and more flexibilty:)
    even when that day really comes, it may will not be our resposibility to do the firsthand job
      

  22.   

    and of course, you can define the first byte as the major type, and the second one byte (or more byte) as subtype, then your worry will be even impossible.
      

  23.   

    and finaly, it's not means i will define the protocal arbitary, it just means it's a better way of my solution. the example structures above is not the real structrues in my project, just for illustration's sake. how to arrange the first byte, and how to design the structres also deserves hard work
      

  24.   

    by the way, when you are updating server sides again and again to improve performace, it's imposible that the client sides should always remain the same and needn't an update to improve customer's experience.IF you won't do that, your boss will ENFORCE you to:)
      

  25.   

    well,i belive your idea is right.
    and i've found our diffirenct now, your solution suits large-protocal-projact,and my solution suits small-protocal-projact. no one goes wrong, and we are all right:)
      

  26.   

    by the way, when you are updating server sides again and again to improve performace, it's imposible that the client sides should always remain the same and needn't an update to improve customer's experience.even IF you won't do that, your boss will ENFORCE you to:)
    ===============
    and then the opportunity to improve the designe of the protocal is come:)
      

  27.   

    maybe you will guess it will only make the protocal more and more complix and expensive to maintain.
    well it's not the truth.
    first, it's a long time for you to use up the namespace
    second,you can simply distinguish between old-protocal users and new-protocal users at login time, you can return an error message to your too old-protocal user at login time too.
    third, when old and new protocal users are distinguished you can suggest your old-protocal users to updata their client side.or you can update the client side automatically, then your worry is gone:)
    fourth, when you find a clever improvince to your protocal, it's not a difficult thing to maintain compatibility with your older version.
    and i believe a large chagne of the protocal is not the often thing, even if it occurs, it also means you have produced a significantly more wounderful product, then there is no reason that your costumer refused to have an update.
    well so much have talked about it, it's the time to go on our work. best wishes!
      

  28.   

    all come to one fact -------- dynamic improving, that's all
    you can dynamiclly improve your functonality, you can also dynamically improve your protocal, they are the same animal.
      

  29.   

    Windows Media Video 9是Windows平台下目前最新的,也是目前效果最好的一种压缩算法,因为如果它比mpeg 1,2,3,4,h261,262,263,264要差的话,微软是不会推出来的,那个Windows Media Voice也是一样的,呵呵
      

  30.   

    为了减少不必要的难度,以加快速度,现在决定不自定义Allocator了,就弄两个Filter,这两个东东弄好后,就可以实现整个流程了:)
    另外,经过测试,压缩,解压缩改为MPEG42和Windows Media Audio,其它基本不变,祝各位新年快乐!
      

  31.   

    http://community.csdn.net/Expert/topic/4509/4509991.xml?temp=.7954065
    网友一席话让我蠢蠢欲动!才1.5k工资,不干了!
    年后继续找工作