CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
可用分押宝游戏火热进行中... 专题改版:Java Web 专题
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  专题开发/技术/项目 >  网络通信

如何设计一个协议,使得一千台PC知道是否在线

楼主qps2006()2005-12-30 09:25:56 在 专题开发/技术/项目 / 网络通信 提问

 
     
  有一千台PC,每台都知道这一千台PC的IP地址,如何设计一个协议,使每台PC知道其他PC是否在线?  
   
  最笨的办法是每隔几分钟就要求每台PC向其余999台PC发一个UDP包,以示在线。有更好的办法吗? 问题点数:20、回复次数:61Top

1 楼superdreamer(只懂一点点!)回复于 2005-12-30 09:37:04 得分 0

参照QQ   MSN的实现方法Top

2 楼qps2006()回复于 2005-12-30 09:44:49 得分 0

谢谢楼上的,哪里有MSN实现方法的资料?Top

3 楼netsys2(来电!)回复于 2005-12-30 10:24:15 得分 0

可以采用中间服务器体制,设置一台SERVER,所有计算机开机后都到SERVER登记,SERVER将把已登陆CLIENT信息发给你。Top

4 楼qps2006()回复于 2005-12-30 11:48:55 得分 0

回楼上的:每台PC确实要在服务器上登陆,但登陆后如何确定是否仍然在线?Top

5 楼netsys2(来电!)回复于 2005-12-30 12:39:17 得分 0

方法一:CLIENT退出时向SERVER发出退出申请  
   
  方法二:SERVER定时向各CLIENT发出查询。  
   
  反正都比你原先的N*(N-1)效率高Top

6 楼qps2006()回复于 2005-12-30 16:03:24 得分 0

感谢楼上的!  
   
  您的方法也有问题,第一,有的用户离线时未必报告服务器,比如死机、断电;第二,服务器查询时发现离线PC后还要通知每台PC,注意,我的问题是“使每台PC知道其他PC是否在线”Top

7 楼herryhuang(Herry)回复于 2005-12-30 22:44:41 得分 0

1.服务器端:每隔60秒,发送一份广播查询报文,然后开始等待60秒。  
   
  2.PC收到查询报文后启动一个定时器,时长为0~60秒间的一个随机值,定时器超时后,向服务器发送一份响应。(之所以要启动一个随机的定时器,是为了防止广播风暴)  
   
  3.服务器等待60秒后,记录每台PC的状态,如果原本一个不在线的PC本次发回了响应,就记录这个变化。如果一个原本在线的的PC连续3个探测周期都没有响应,就认为已经下线。得出探测结论后,还是使用广播报文向所有设备报告每台PC的状态。  
   
  选项:  
  A.服务器得出探测结论后,发送的报告可以只包含状态改变的信息,对于那些状态没有改变的可以不报告。  
  B.服务器的状态报告报文可以同时作为查询报文。如果报告内容较多,可分为几个报文发送,并使用最后一片作为查询报文。  
  C.PC开机后可发送一份广播报文向所有PC报告“俺来了”,同样的在下线的时候可以广播发送一份“俺撤了”,因为仅仅在开机和关机的时候发送,因此不会有太大的影响。  
  D.两台服务器A和B一主一备,B服务器平常不会进行探测活动,但是如果连续三个周期没有收到A的探测报文,就自动将自己升格为主服务器,接管探测活动,同时使用一些必要的手段使A恢复正常(例如某些高端服务器坐热备份的时候,可以在对方发生问题的时候将对方重启),A服务器恢复正常后,等待120秒,如果在这期间收到了B(现在已经升格为主服务器)发来的探测报文,就将自己降格为备用服务器。  
  Top

8 楼fierygnu(va_list)回复于 2005-12-30 23:51:57 得分 0

楼主没有说明应用环境。局域网、广域网,有没有代理,。。。Top

9 楼qps2006()回复于 2005-12-31 06:55:40 得分 0

感谢herryhuang(Herry)!您给出了测试是否在线的一个算法。  
   
  回   fierygnu(va_list):这一千台PC就是互联网上普通用户的PC。虽然有一台服务器,但服务器的资源(带宽、CPU周期)有限,服务器也是一台普通的PC。所以我希望每台PC使用自己的资源判断其它PC是否在线。  
   
  我来谈一下我的不成熟的想法:  
  1)每台PC在线后立即到服务器上登陆,  
  2)在这一千台PC中任意指定10台作为子服务器,负责检测99台PC是否在线。如果发现离线,则通知自己负责的98台PC和其它9台子服务器,其它子服务器再通知自己负责的PC  
  3)服务器负责检测子服务器是否在线,如果离线,将重新指定子服务器  
   
  以上方案还不完整,请各位多提意见!先谢了!Top

10 楼fierygnu(va_list)回复于 2005-12-31 09:19:20 得分 0

1、所有的PC都要点对点通信吗?按照楼主的意思好像是这样的。。。  
  2、既然大家都是要通信的,断了就知道了  
  3、如果长时间没有通信的需要,断了就断了  
   
  说白了,楼主的应用对可靠性要求那么高吗?Top

11 楼qps2006()回复于 2005-12-31 10:30:57 得分 0

谢谢fierygnu(va_list)!  
   
  所有PC都可以点到点,这样可以减轻服务器的负担。对可靠性没有具体的要求,当然,我希望每台PC能及时了解其它PC是否在线,不要等到很多(比如三分之一)PC已离线,有的在线PC还不知道  
   
  我的应用可以理解为聊天服务器,初始状态是仅聊天服务器在线,然后陆续有PC登陆。任几台PC之间都可以聊天,不必通过服务器。  
   
  我参考了聊天协议(Internet   Relay   Chat   Protocol),所有通讯(聊天)都是通过服务器,所以对服务器要求较高,这一点聊天协议也承认。这个协议没多少参考价值  
   
  有现成的协议可供参考吗?Top

12 楼fierygnu(va_list)回复于 2005-12-31 13:14:16 得分 0

你的服务器就象DDNS服务器了   :)  
   
  按照你的设想,当几台PC不通过服务器聊天时,需不需要其中一台作为服务器?如果一台PC要与多台聊天怎么办?每个PC自己维护聊天组的信息?  
   
  如果不用IRC方式,每个PC需要与参与聊天的PC建立直接连接,对每个PC的要求就高了。  
   
  要不然看看PIM-SM协议,尤其是RPT转SPT的部分,看有没有参考价值?  
   
  Top

13 楼qps2006()回复于 2005-12-31 14:26:32 得分 0

感谢   fierygnu!  
   
  按照我的设想,千余台PC中,一部分在聊天组中聊天,每组一般不超过10人。为了健壮性,我考虑不在每个聊天组中设立服务器,而由每台PC自己负责与其他组员的聊天。是文字聊天,不是视频,所以流量不大,普通PC可以负担。估计每分钟每台PC会在小组中广播2次左右,每次广播内容只需一个UDP包。聊天结束时有一个结果,每个组员都可以向服务器报告。  
   
  每台PC可能尝试与任一台PC聊天,是文字聊天,所以流量不大,但是如果发现很多PC未响应(离线),那么用户会不高兴。所以每台PC应能及时了解其它PC是否在线  
   
  您推荐的协议我不太熟悉,以后有空再看Top

14 楼boox(boox)回复于 2006-01-01 15:32:15 得分 0

广播报文是达不到1000台的,因为有子网或者vlan限制,可以考虑用多播,机器上线的时候加入多播组,这个组定时刷新。Top

15 楼herryhuang(Herry)回复于 2006-01-01 22:36:57 得分 0

首先,如果每台PC都需要“完全依靠自己的力量”来探测其他PC的状态,实际上非常的浪费资源,如果每分钟进行一次探测,实际上需要发送1000^2这么多的报文(无论你采用哪种方式,双方的心跳检测都是必须的),因此实际上不可行。  
   
  你计划的“任意选择10台”作为服务器,实现起来难度很大,因为程序只会按照设定好的逻辑工作,不会“任意”选择,那么选择的策略就要想好。另外,到底谁负责哪些PC是,否需要这些服务器之间进行协商?否则是不时候出现某些服务器忙得要死,另外几台闲得要命?而且从维护上说,维护10台服务器的成本要高得多。如果一台感染了病毒的PC不幸被选中作为服务器,那么很可能出现一些意外的情况,在这种情况下你就必须保证1000台PC全部没有问题,这比添置一台服务器的成本高多了。  
   
  我的建议是,增加一台服务器(或者利用一台现在还有空闲计算资源的PC),并保证它的可靠性(比如,有专人维护),其他的某台PC出故障的时候才不会影响到整个网络。  
   
  广播报文是可以达到1000台的,呵呵,只要网络拓扑允许,一个A类网络广播地址可以广播给2^24-2台主机。Top

16 楼fierygnu(va_list)回复于 2006-01-01 22:56:00 得分 0

广域网上是无法广播的   :(Top

17 楼herryhuang(Herry)回复于 2006-01-02 00:06:39 得分 0

他这个应用应该是局域网:)  
   
  即使在广域网上,也存在假设服务器的问题,这种情况下就比较接近即时通讯了。要将广播换成单播。  
   
  至于组播,因为安全性与抗干扰性的原因,建议尽量不要使用。  
   
  不过PIM-SM这个想法不错,但是没办法保证每台PC都老老实实工作(也就是我说的可靠性问题),还有就是实现起来复杂点。Top

18 楼qps2006()回复于 2006-01-02 10:04:46 得分 0

感谢herryhuang(Herry)的宝贵意见!  
   
  可能是因为我没说清问题。我是想把我的一台普通的PC设成聊天服务器,想参与聊天的用户须运行我提供的聊天软件。但是这台服务器资源(带宽、CPU)有限,所以我希望用户使用自己的PC来检测其他用户是否仍然在线  
   
  我想“任意选择10台”并不难啊。用户端的聊天软件运行后都先到服务器上登陆,服务器自然知道他们的IP,服务器可以按登陆顺序,指定第1、101、201...台作为子服务器负责检测99台PC是否在线,服务器可以发个包告诉他们那99个IP地址  
   
  其实服务器用的就是普通的宽带(有线猫),ISP称有1M,实际高峰时肯定远小于1M,服务器要负责新用户注册、老用户登陆、聊天组聊天结果的记录,负担不小(能负担吗?),我估计同时在线最多可达几万人,假定一半加入聊天组,每组不超过10人,每个聊天组10分钟左右需向服务器发一个包,报告聊天结果。这样的负担服务器能承受吗?所以没有多余的带宽来检测用户是否在线。Top

19 楼qps2006()回复于 2006-01-02 10:15:09 得分 0

关于您说的“感染了病毒的PC”,这就好比子服务器随时可能离线,这个问题肯定要考虑。这有点类似分布式计算,肯定要考虑每台PC的可信度  
   
  我总觉得我的方案(1台管99台)并不好,肯定有更好的方案,Top

20 楼fierygnu(va_list)回复于 2006-01-02 10:19:04 得分 0

你的应用环境,我认为还是IRC好。:(Top

21 楼qps2006()回复于 2006-01-02 11:58:09 得分 0

IRC也有服务器负担过重的问题  
   
  我总想让我的服务器免除检测子服务器是否在线的负担,比如让用户的PC向服务器报告离线PC,如果有三台PC报告某台PC离线,那么确实离线,这就在一定程度上解决用户PC可信度的问题Top

22 楼superdreamer(只懂一点点!)回复于 2006-01-05 09:46:40 得分 0

用广播的方式肯定不行  
  用IRC的方式服务器负担过重,   若以后要扩展的话,也困难!  
  最好的方式是一台SERVER,   负载登陆,注册,   以后CLIENT对话采用点对点,   这样一台普通的PC处理上千台是没有问题的,   若以后有上万台,升级硬件即可  
  检查在线与否参照QQ   MSN的实现方法  
  另不知你的CLIENT是在LAN内还是都有公有IP,若是后者,   哪好办,   不过建议都要考虑!  
   
  要实现以上这些东西,   哪参照QQ   MSN的实现方法就OK了,这样就算以后有多少CLIENT,   而且不管是公共IP还是在LAN内通过NAT的方式都可以,    
   
  呵呵,   看来楼主还是没有花时间去研究QQ   MSN,   象你说的子服务器的方法我觉得可行性不好,   这样结构太复杂,   而且效果也不一定好!     有QQ   MSN这样好的参照,为什么不花点时间去研究一下呢?Top

23 楼ensoniq()回复于 2006-01-05 17:35:08 得分 0

那不是一回事。MSN好友名单上有1000人吗?他的要求是1000人都可以知道其他所有人是否在线。  
   
  直觉上楼主的方案是可行的,不过实现起来比较复杂,感觉有点类似GFS的Master   Server结构。Top

24 楼qps2006()回复于 2006-01-05 22:08:09 得分 0

感谢两位(superdreamer和   ensoniq)参与讨论!  
   
  superdreamer:能具体谈谈QQ   MSN的实现方法吗?   CLIENT在LAN中会有什么问题?  
   
  我已有了更好的想法,老方案(1台管99台)已被我淘汰。我想让1000台PC按IP地址排序组成环,每小时的第1、11、...51分钟开始检测,由第1台向第2台发一个包,第2台收到后向第一台回1个包,然后再向第三台发.如此接力下去,如果第2台离线,则第一台向第三台发包,并在包内写上“第二台离线”,另外还可以同时从几点开始(比如从第333、666台也同时开始)  
   
  各位对以上想法有何高见?  
   
  Top

25 楼qps2006()回复于 2006-01-05 22:11:18 得分 0

superdreamer:网上哪里可以找到QQ和MSN实现方法的资料?谢谢!Top

26 楼ablewindy(我是【风子】我怕谁)回复于 2006-01-06 09:35:20 得分 0

每个客户端用TCP维护一个和服务器的连接,断了服务器就知道啊!  
  服务器知道了就通知所有在线的用户。  
  有客户端上线也一样!  
   
  为了防止频繁的上下线,可以采用服务器记录一段时间内的上下线用户记录,一次性通知所有在线用户的方法。当然每次上线的用户需取得一个全部在线用户的列表!Top

27 楼qps2006()回复于 2006-01-06 09:41:45 得分 0

谢谢ablewindy,但您的方案对服务器要求太高  
   
  我的新方案也有问题,  
  1、第一台离线怎么办?这容易解决  
  2、第二台在回复确认后离线(未向第三台发一个包)  
  Top

28 楼superdreamer(只懂一点点!)回复于 2006-01-06 10:29:18 得分 0

CLIENT在LAN中会有什么问题?  
          这样外面怎么能连进来,在LAN与WAN是有很大区别的,   就是P2P的问题了  
  MSN好友名单上有1000人吗?  
        你的MSN上没有,   但你可以加到1000啦,   我想这没有问题!  
   
  我不知道你的具体应用,   就算文字聊天,有1000人同时在组聊吗?    
      既然是聊天,   肯定是要熟人才聊呀,   哪就可以想MSN   QQ那样添加好友,   也可以查询所有在线的  
   
  ===》我已有了更好的想法,老方案(1台管99台)已被我淘汰。我想让1000台PC按IP地址排序组成环,每小时的第1、11、...51分钟开始检测,由第1台向第2台发一个包,第2台收到后向第一台回1个包,然后再向第三台发.如此接力下去,如果第2台离线,则第一台向第三台发包,并在包内写上“第二台离线”,另外还可以同时从几点开始(比如从第333、666台也同时开始)  
      这样你的结构不是更复杂了,   现在是1000台,   更多呢?   还有你的IP地址是固定的吗?  
   
  QQ   MSN你可以在GOOGLE里搜索一下,   不过主要还是去抓数据包来分析,Top

29 楼qps2006()回复于 2006-01-06 14:14:53 得分 0

感谢   superdreamer  
   
  我早已用GOOGLE搜过,未查到。我这里也没抓包工具,Linux下有tcpflow,但MSN和QQ不支持Linux。估计MSN和QQ的实现都需要带宽,我没有。算了  
   
  目前我计划每个聊天室1000人,人数超过后另外组成聊天室,也可拆分1000人的聊天室。每个聊天组一般不超过10人。用户IP变化后应重新登陆。Top

30 楼ensoniq()回复于 2006-01-06 14:37:16 得分 0

印象中MSN的断线检测是不完备的,如果你直接切断网线,你的好友还会看到你在线,一直到他向你发送消息为止,他才知道你下线了。据此可以判断MSN的上线下线可能是客户端自己向服务器发出的事件,服务器再根据好友的相关性转发通知。如果客户端关机下线则没有直接的检测。Top

31 楼superdreamer(只懂一点点!)回复于 2006-01-06 17:15:58 得分 0

:)Top

32 楼qps2006()回复于 2006-01-06 18:15:32 得分 0

感谢ensoniq()   !  
   
  MSN   和QQ都是不公开代码、协议,使用服务器来检测用户是否在线,而我是利用每个用户的机器来检测,实际上拥有无限的资源(带宽、CPU),相当于分布式计算,理应做得更好,关键是协议的设计  
  Top

33 楼herryhuang(Herry)回复于 2006-01-07 00:15:30 得分 0

设计一个分布式的高可靠性协议比买一台可靠的服务器要贵得多!  
   
  实现的复杂程度是必须要考虑的问题,如果你实现一个完美的协议需要几个月甚至一年的时间,它的价值就很值得怀疑了。  
   
  如果我是老板,就希望用现有的可用技术,满足我的的最小需求,同时将成本降至最低。  
   
  我看了楼主这几天的讨论,中心的思想就是想要一个可实现分布式、动态选择核心服务器、多主机对称处理的协议,这样的协议不是没有,你可以参考OSPF路由协议(该协议可以满足几乎任何组网,当每台主机都配置32位掩码的LOOPBACK地址时,就与你的需求完全相同,只要在其他主机上能看到这台机器的路由,那就说明它在线,如果看不到路由,那就是不在线),问题在于你真的需要这样复杂的一个协议吗?这样的一个协议从设计到编写代码到最终调试稳定,至少需要一年半的时间!  
   
  无论从实现的难度来看,还是从计算的复杂程度、网络的流量负荷来看,采用一台服务器集中管理都是最经济有效的!因此我们也可以理解为什么即时通讯软件也没有采取“无集中服务器”的方式。  
   
  你这里并不存在“数量不可预期”的用户,也不存在“地理位置随机”的情况,在这样的条件下采取过于复杂的实现是很不经济的。  
   
  如果你还是坚持自己的想法,公开的代码也不是没有,即时通讯软件可以参考GAIM的源代码。而OSPF路由协议除了可以看到公开的RFC,Linux内核也实现了该协议。Top

34 楼qps2006()回复于 2006-01-07 12:54:56 得分 0

万分感谢herryhuang非常专业的意见!!!  
   
  但我没钱买带宽,也不需要高可靠性。我的击鼓传花的方式基本可行,实现起来也不难  
   
  我有空会去看看GAIMTop

35 楼ensoniq()回复于 2006-01-07 15:59:25 得分 0

在sourceforge上有很多的   :)Top

36 楼herryhuang(Herry)回复于 2006-01-07 19:31:32 得分 0

没有理解楼主这个“击鼓传花”协议的内容,再说得详细些。  
   
  从我的理解来说,所谓“击鼓传花”也就是说每台主机只能看到他“左边”和“右边”这两个“邻居”,既然左右没有区分,也就不应该有单向的数据链,如果要击鼓传花,也应该是双向的。  
   
  先不讨论具体的细节,请思考几个问题:  
   
  在这种环境下,每台主机都绝对信赖他的邻居,并且将他从一个邻居收到的数据送给另一个邻居,如果某台主机出现问题(比如发送了一份错误的数据报)、或者在一次传输中信号干扰较严重,这个错误的信息就会被不断传播甚至放大。  
   
  楼主的组网拓扑应该不是环形的,现有的大多数局域网都是星形拓扑结构,在一个星形拓扑结构的网上采用这种环形方式,开销要大得多,因为每一个报文都要经过中心节点,而如果采用击鼓传花的方式,一个探测周期需要收发大约4000个报文(1000台主机,双向,如果是单向的话,就需要将花传两圈,不然你就只能知道一边邻居的情况,另一边的恐怕就要下个周期才能知道)。这个开销其实比采用服务器的开销要大。  
   
  按照楼主的计划,第1台、第333台、第666台定时启动探测活动,如果这几台全部意外的down掉了(也就是说没有发出“俺走了”这样的信息),那么第2台、第334台和第667台如何接替他们的工作?假设他们在那个应该收到、却没有收到消息的时间点之后1分钟自动启动探测,OK。假如这三台也意外DOWN掉了,再下来的三台该等多长时间呢,是否每台机器都需要清楚自己等待的最长时间?如果有些机器down掉了,每台机器都应该调整这个等待时间?  
   
  可以肯定地是,如果每台机器都认为应该在10分钟准时收到消息,肯定是不对的,这样很容易造成消息风暴,那么每台机器就需要知道自己距离那个发起探测的机器“有多远”,这是个悖论,因为现在它根本不知道那台机器在线不在线,怎么可能知道它有多远。Top

37 楼qps2006()回复于 2006-01-07 21:21:58 得分 0

再次感谢herryhuang的宝贵意见  
   
  注意,我对可靠性要求不高。每个用户登陆后都会获得服务器时间,这样就统一了时间;应用的环境就是公众使用的互联网  
   
  关于第一台PC离线的问题:解决的办法很多,比如可以由服务器负责检测第一台;也可以多设几个起点,多台PC同时离线的概率不高;也可以变化起点:第一分钟由第1、501台,第16分钟由第126、626台,第31分钟由第251、751台,...(每小时4个周期,2个起点),;另外还可以改变排序方式,第一个周期根据IP地址的第一个字节排序,第二个周期根据第2个字节排序;另外在检测过程中还可以交换自己掌握离线用户  
   
  我不准备让用户判断起点是否已离线  
   
  如果以后真的实现了,希望你来看看,请留下伊妹  
  Top

38 楼herryhuang(Herry)回复于 2006-01-07 23:29:48 得分 0

无言了,最后一点忠告,先在VC下模拟。Top

39 楼herryhuang(Herry)回复于 2006-01-07 23:42:23 得分 0

我的email不必告诉你了,因为你说的这种协议根本就转不起来。。。。。。  
   
  你只是点点滴滴拼凑的想法,根本就没有从全局去考虑过这个需求。  
   
  你前面说不用服务器,后面又说用一台服务器去检测离线,那到底有没有服务器?  
   
  如果有服务器用来监测离线,那就用不着每台机器发出消息后等待了。  
   
  随机的选择起点:你都不知道现在谁在线,怎么随机选择?  
   
  击鼓传花:如果发出消息后没有收到回音,等待多长时间就认为下一台机器离线了?3秒?那么1000台机器中如果有500台离线的话,这个“花”传一圈就要1500秒,接近半个小时。  
   
  变化的起点:怎么决定?谁来决定?随机的?谁想启动就启动了?  
   
  建议你还是先写一个“需求文档”,把自己的思路整理整理,网络环境是啥样,最多承载多少节点,反应时间是多少,允许的错误率是多少等等。  
   
  Top

40 楼ablewindy(我是【风子】我怕谁)回复于 2006-01-09 09:34:45 得分 0

其实这个问题估计在很多相类似的应用中都会碰到,我想首先要明确做这东西的最底限需求,是必需在任意一个用户非法退出时其它用户都必需马上知道吗?我想这基本就是不可能的。即使是有一条TCP的连接,非法退出后要检测到也要一定的时间。  
   
  既然不可能马上知道,那就考虑可容忍的最大时间啦。  
   
  服务器在一段可接受的时间内轮询的方法不挺好嘛?一千台机器,每次轮询用10ms,最多时一次轮询也就10s,10s同步一次也不算久吧。至于用户在聊天的过程中一旦和要聊天的目标机通讯不成功就可以标识该用户不在线罗!  
   
  其实,以上讨论只是针对非法退出,比如程序Down掉了或者被拔掉网线了之类的。我想大部分情况用户还是会正常退出的吧!所以把一个低概率的事件设计得过于复杂,不知有没有意义哦!  
   
  再都,非法退出时其它用户有一定的延时知道此用户离线也是情理之中的啊!Top

41 楼superdreamer(只懂一点点!)回复于 2006-01-09 10:02:02 得分 0

蛮佩服     herryhuang(Herry)   (   )   的回答,   也蛮佩服楼主的想法,   我是喜欢简单的东西,   所以实现任何功能,我都尽量按简单的思路来想,   尤其是程序结构,   我是喜欢MODULE式,   也不喜欢逻辑超复杂的那种结构,   每次听我的同事说他写的程序逻辑怎么怎么复杂,我就头大!  
   
  MSN   QQ的协议是没有公开,   但对做网络的来说,   想要知道他的大部分思想还是容易的,   呵呵,   我是不是中了MSN   QQ的毒了,   不过我觉得聊天软件来说,   MSN   QQ哪肯定是其中的佼佼者,       希望楼主能早日实现你的宏伟想法,Top

42 楼qps2006()回复于 2006-01-09 17:15:31 得分 0

感谢ablewindy和superdreamer的参与!herryhuang可能没明白我的意思,尽管水平很高  
   
  诚如ablewindy所说,本楼主要解决用户非正常退出,我没法给出具体要求。“服务器轮询”对服务器要求太高,检测一台仅需0.01S?UDP包一个来回仅需0.01S?  
  顺便提出"用户如何传播信息"这个问题,(比如用户退出时发出离线信息),通过一传十、十传百?怎样解决路径中的离线用户?通过设定多条传播路径,注意,用户退出时可不想等很长时间。少数用户未收到是可以接受的。  
   
   
  superdreamer:我哪能挑战MSN和QQ?  
   
  对了,其实每个用户掌握的千余个IP不完全相同,在击鼓传花中,如果某一个检测周期的起点是1/3处、2/3处,那么可能有多台PC以为自己在1/3处。为了限制流量,我决定每个检测周期中每台PC只接力一次Top

43 楼ablewindy(我是【风子】我怕谁)回复于 2006-01-11 10:11:02 得分 0

我觉得一般的需求更多应该考虑正常情况下。  
  你期待解决某个人或某几个人的非正常退出意义不大。  
  要是你程序会经常崩掉,我觉得还不如多花时间解决软件BUG呢!  
   
  往往简单的方法是最有效的!  
  还有,真怀疑你做的东西会有一千个人聊天吗?还是只是抱研究的态度在尝试与学习?Top

44 楼Victorianism(风尚)回复于 2006-01-12 23:45:30 得分 0

来谈谈我的看法:  
   
  用户以1分钟的频率向服务器发送心跳包(KeepAlive),服务器使用数据结构或数据库记录每个客户端发来的心跳包到来的时间.服务器起动一个定时器定时检查这些心跳包的时间是否超时(计算当前时间与心跳包的时间差大于1分钟).如果某个用户超时则通知其它用户该用户已下线.Top

45 楼Victorianism(风尚)回复于 2006-01-13 09:34:15 得分 0

假如一分钟有10个用户意外断线,服务器在这一分钟里要发一10000个报文.我想,一个用户里的好友列表不可能同时有1000人在线吧,就连MSN,QQ这么成熟的软件都没达到这个数.Top

46 楼qps2006()回复于 2006-01-13 15:55:20 得分 0

感谢ablewindy和Victorianism!!  
   
  ablewindy:我的网站正在开发中,到底能有多少人来?如果成功,几千人应该没问题,如果失败...  
  我也在考虑是否要实现这个检测功能...浪费各位时间了,再问一下:检测一台PC只需0.01秒?Top

47 楼ablewindy(我是【风子】我怕谁)回复于 2006-01-16 15:31:20 得分 0

一个UDP来回具体时间不知道,如果是局域网内,正常情况下10ms应该足矣,当然,如果你的网络数据量狂大或考虑到你的程序的处理逻辑实现的问题,那就不一定了。  
   
  要是广域网,那就难说了,因为路由,指不定要多少时间呢!  
   
  而且,发送和接收你肯定是可以同时进行的啊,你管他接收到回复要多久呢?你发轮询下去,最后看1秒后有没有收到回复就行了啊,未收到之前你还是可以发送其它轮询包的啊!Top

48 楼qps2006()回复于 2006-01-16 17:00:47 得分 0

感谢ablewindy的专业回答!!  
   
  我是在互联网,相当于广域网,我想也不可能是0.01秒,我可没有带宽和CPU来轮询,也没必要,不过我会试试Top

49 楼xkst(spark)回复于 2006-01-19 22:43:24 得分 0

做过一个类似的轮询,所有的客户都和服务器上有一tcp连接,服务器定时向所有上一轮检测到(连表中)户发送检测数据,同时维护这连表(发送成功为在线)Top

50 楼happy__888([顾问团]寻开心 www.e-jjj.com)回复于 2006-01-20 14:25:40 得分 0

1.   服务器+心跳包  
   
  一台作为服务器,其他用户登陆后就每隔一个时间间隔,比如1s,向服务器发送特定的在线信息(心跳包),服务器根据是否在一定间隔内比如3s,收到信息包判定该pc是否在线,并更新其在线状态到一个统一的状态表当中去  
  其他机器可以从服务器获取这个状态表  
   
  2.   如果是p2p下载服务那种,服务器端登陆了在线的客户的信息  
  客户端提取一次在线客户表后,自动判断哪几个速度快,然后与其建立单线的连接  
  客户端并不需要总是需要从服务器即时了解其他客户是否在线,可以在很长的一段时间内比如1分钟或者10分钟更新一次就可以的,因为只要保证客户端同时和多个客户之间有联系就可以,并不一定要求非得实时和最快的有联系Top

51 楼wjlsmail(小脖领)回复于 2006-01-21 13:10:47 得分 0

组播可以实现吧,登录时向组发消息,退出时再发消息,根据消息更新列表Top

52 楼boox(boox)回复于 2006-01-21 22:40:34 得分 0

心跳包不用发那么频繁。TCP的老化时间20多分钟呢,ARP表默认老化时间高达3个小时。1,2分钟发一个就行了,经济,好用。  
   
  实现的体系架构建议看一看PIM-SM协议,学习一下,在应用层实现出来。选出一些汇聚点,可以大大减少网络负担和服务器计算负担。Top

53 楼yangzhenhai(叉子)回复于 2006-01-23 14:23:08 得分 0

我问楼主个问题,服务器程序知道客户登陆以后,是把socket保存起来,还是就保存客户的IP地址?  
  服务器程序需不需要每个线程对应一个客户访问?我的应用最多只会有几十个人同时在线.Top

54 楼chenqing1128(Alex)回复于 2006-01-26 10:45:31 得分 0

最好加入多播组.然后每个pc都向组定时声明自己.比如开机的时候声明一下.具体来说可以如下做:  
  1.每个机子上有两个模块.一个是Controlpoint(控制端).一个是Device模块  
  2.开机的时候ControlPoint向多播组发送一个search消息.其他机子的Device设备收到后要定点(单播)向该机子回一个NOTIFY消息.同时ControlPoint中要有一个线程负责轮询将每个机子的expire(失效时间)不断的减少.当Device的expire快(记住是"快"不是"已经")减少到0的时候.ControlPoint要定点(单播)向该Device再次发送search消息(记住是定点).该Device收到后再发送确认消息.  
  ControlPoint就把expire再设为最大值(或是Device所声明的值).如果expire到了0还是没回消息.那么把该设备从列表中删除,认为该设备已经下线.  
  当然当ControlPoint收到NOTIFY消息是先检查该设备是否在列表中如果不在,那么添加该Device到列表,expire设为最大值(或是Device的NOTIFY消息中所声明的值);如果存在,那么只需要将Device的expire设为最大值(或是Device的NOTIFY消息中所声明的值)即可.  
  当ControlPoint模块收到Bye消息的时候就把该Device从列表中删除.  
  3.开机的时候Device模块向多播组发送一个NOTIFY消息声明自己的存在.当收到search(别人的机子的ControlPoint模块发出的)消息的时候,就定点(单播)向该ControlPoint发送一个NOTIFY消息声明自己.  
  如果机子关闭了(下线)那么就向多播组发送一个Bye消息.  
   
  以上是根据upnp协议改编而来,去除了里面的服务定制和操作部分.  
  可以参考www.upnp.org网站  
  Top

55 楼zzwu(未名)回复于 2006-02-03 16:54:32 得分 0

服务器端有一个属性,叫"ActiveConnectons",能指示当前打开的cliect   Socket的数目,可以监听这一个数据,如果它变少了,再去查另一个叫"Connections[]"的属性,这是一个已打开的连接列表.Top

56 楼gogowhy(123)回复于 2006-02-07 08:16:23 得分 0

markTop

57 楼domino_question()回复于 2006-02-07 09:29:57 得分 0

我有个很好的办法:   你在每台机器上装个QQ,这样谁在线你都知道了.哈哈Top

58 楼naiza(叼虫小鸡)回复于 2006-02-09 09:20:18 得分 0

markTop

59 楼zjpixyniannian()回复于 2006-02-09 15:09:58 得分 0

markTop

60 楼wls12342004(青青子木)回复于 2006-02-09 16:49:01 得分 0

关注中,还真没想过这个问题,关注中!Top

61 楼borland_boy(疯狂的兔子)回复于 2006-02-10 11:25:37 得分 0

用125个字节表示1000台机器的在线情况  
   
  一台机器作服务器  
  其他的机器每32台一组  
  每组一台组服务器(不固定)  
   
  每组的32台机器中第一个登陆到服务器上的机器作为这32台的服务器  
  其他31台在登陆的时候先找大服务器然后大服务器通知它去找他所在组中的服务器  
   
  每个组的服务器负责管理自己组内的机器是否在线  
  定期向服务器发送再线情况32台机器(4个字节)  
  服务器返回125字节的数据,然后组服务器通知组内32台机器  
   
  服务器定期检查32个组服务器是否在线,如果不在线就从该组另外寻找一台机器作为服务器  
  如果没有机器再线就等待这32台机器重新登陆  
   
  见笑了Top

相关问题

  • 怎么设计用户层协议?
  • 请教tcp/ip协议设计.(用汇编语言)
  • 协议设计中定时器如何实现?急
  • PC键盘如何设计?
  • 讨论一下应用TCP/IP协议的服务器的设计方法
  • 如何设计一个类,使得这个类必须在堆上实例化?
  • 怎么使得继承自CollectionBase的Items在设计时的内容持久?
  • 如何设计网络协议,在单Server上确认10000台Client的工作状态
  • 如何?怎样?给你100分,你能改变整个地球!(应用层协议设计)
  • 向网络程序员请教一下:“简单应用层协议的设计与开发”方面的问题

关键词

  • p2p
  • 服务器
  • pc
  • 检测
  • 用户
  • 聊天
  • 协议
  • msn
  • 客户
  • 主机

得分解答快速导航

  • 帖主:qps2006

相关链接

  • CSDN Blog
  • 技术文档
  • 代码下载
  • 第二书店
  • 读书频道

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
世纪乐知(北京)网络技术有限公司 版权所有, 京 ICP 证 020026 号
北京创新乐知广告有限公司 提供技术支持
Copyright © 2000-2007, CSDN.NET, All Rights Reserved
GongshangLogo