我使用VB6\WINSOCK控件、TCP协议开发了一个OICQ的聊天软件,WINSOCK控件是支持多线程的,但是如何使服务器同时接收多个客户断的请求(包括连接,信息转发),这里我使用了FOR循环因为服务端要从上线用户列表中找到要此用户,但是当这个FOR循环没有执行完毕的时候,服务器又接到了下一个用户的请求,又进入了一个FOR循环,这时上一个循环就会被终止,可能导致上一个信息发送失败。VB6是单线程的,除了使用“多线程”外,完全依靠WINSOCK控件的多线程,能否解决上述的问题,或者您有更好的解决方式或办法?请赐教!非常感谢!!A发送信息给B,A将信息发送给服务端,服务端再将信息转发给B,以下是服务端的代码片段。我担心的是如果此FOR循环还没有执行完毕,服务端又接收到一个请求,那么此FOR循环在没有找到B用户的时候就可能被终止,开始了一个新的FOR循环,导致B将收不到A的信息。有没有一种办法可以解决此问题!!!最好不使用多线程,当然如果您有更好的方法,请赐教,谢谢!!
 For u = 0 To intMax '查找B用户
   
       
            If ServiceSocket(u).State = 7 Then
                If UserInfo(u).InUse = True Then
                    
                   
                  
                    ServiceSocket(u).SendData "信息" 
                   
                    DoEvents
                    End If
                    
                   
                End If
           
    Next u

解决方案 »

  1.   

    Private Sub sckSocket_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    Dim Socket As Socket
        '由新装载的控件接受客户的连接请求
    On Error GoTo err
        If Index = 0 Then
           Set Socket = sckSocket(sckIndex)
               Socket.Close
               Socket.Accept requestID
           DoEvents
        End If
        Exit Sub
    End Sub
      

  2.   

    Surpass(网络飞狐)     您的意思是,每次收到用户请求都加载一个WINSOCK控件?我的winsock控件建立的是索引的:winsoch(index),但是服务端在中转用户信息的时候,怎么办?
      

  3.   

    zyg0(影子(转了1圈,我又回来了)    使用数据库存,还是需要使用FOR循环来查找用户的,我就是这么做的,但是下服务端接到下一个用户请求时,可能会破坏这个FOR循环,但是我发现下一个FOR循环结束后,上一个循环还会接着循环,比如从50处中断的,它还会接着50往下循环。
      

  4.   

    这是winsock的一个bug.  在后来系统空闲的时候只发送最后一个给记住的send.其他的存在了发送缓冲区  .所以以后发送给其他客户的时候一并受到延时函数里面应该不是死循环而是用doevents腾出时间执行send  
    或者直接写doevents也行  
    另外,不要采用for的方式,而是  
    dim  sck  as  winsock  
    for  each  sck  in  winsock1  
           sck.senddata  "sysy"  
    next  sck  
    set  sck=nothing
    用for in的方式,如果某客户短开的时候unload了winsock(2)就会出错.  比如1,3还存在的时候
      

  5.   

    tztz520(午夜逛街)   我也想过使用TIMER数组来解决这个问题,可是会比for循环的速度慢很多。不知道您是怎样做的能将您的片段代码,发送给我吗?[email protected]
      

  6.   

    zyg0(影子(转了1圈,我又回来了)    使用了控件数组
      

  7.   

    cpio(就这么简单)     您的想法我没有尝试过,您能再详细的描述一下吗?这样做的话,当服务端又接到一个客户的信息,会不会也停止您说的这种循环方式?
      

  8.   

    tztz520(午夜逛街)    您指的是我的聊天软件,客户端与客户端传输的数据只是文字信息,没有任何其他的内容。
      

  9.   

    给各位回复和支持我的朋友:    我的程序是在他的基础上改的,http://www.cn700.com/Down_144/20041023141818.html,请给位下载后看一下客户端和服务端的程序,看看是否会出现我说的问题,如果存在应该怎样更改?
      

  10.   

    TO tztz520(午夜逛街) 
       cpio(就这么简单)
       zyg0(影子(转了1圈,我又回来了) 
       Surpass(网络飞狐) 我的程序是在他的基础上改的,http://www.cn700.com/Down_144/20041023141818.html,请给位下载后看一下客户端和服务端的程序,看看是否会出现我说的问题,如果存在应该怎样更改?
      

  11.   

    去掉DoEvents,一般在对同一Winscok连续使用SendData之间要加DoEvents,但在控件数组中循环,是对不同控件,不需加DoEvents,否则会有麻烦。
    循环后要加上DoEvents,或退出所有调用前,不再有SendData就可以了。
      

  12.   

    真不好意思,我最近在研究.net没时间看你提供的代码,等几天把]
      

  13.   

    TO  homezj(小吉)     按照您说的办法,服务端就可以响应多个客户同时并发吗?请指教!
      

  14.   

    TO  homezj(小吉)
        我使用的是winsock控件数组,我给多人发送信息的时候用的是循环,请问在winsock(1).SendData  "111"
    winsock(2).SendData  "111"之间是否增加Doevents?
      

  15.   

    其实在SendData之后加Doevents是一种习惯用性用法,有时并不是必须的,加的目的是为了让Winscok有机会把数据发送出去,防止前后两次数据连接,使接收端只产生一次事件。但网络环境复杂,就算你加上Doevents,也并不能保证接收端不会只产生一次事件。若你在每个发送数据结尾加一个结束标志(只对String有效,Byte数据应按长度识别),就不用怕连接现象了。明白了道理就行,说再多也没用,加与不加你可便改便试,实践得出的结论最可靠。响应多个客户同时并发,是系统支持的,但到VB处理时,仍是单线程的,只要没有Doevents在中间干扰,你一样可排队顺序处理。建议你学一下Windows的消息机制,接收到的数据可加入到一个集合中排队,用个Timer按到达的先后顺序进行处理,就不会乱了。
      

  16.   

    嗯~这涉及到一个设计概念!也不会是三言两语就能说得明白.在微软的网页上,关于召唤你使用VB.net那有这么一句:VB6不能实现控制台,多线程,服务等应用.其中的服务就是楼主你这样的应用啦!又因为winsock这个控件自身设计上的失误,所以要从另一个角度去解决这个问题了!不要问我winsock有什么设计失误!但我可以告诉你,不要用一般的看法去看待DataArrival,与SendComplete这两个事件!
      

  17.   

    TO homezj(小吉)   qyii(没读过大学)   如果我的客户端采用vb6,服务端采用vb.net是否可以解决并发的问题?
      

  18.   

    哈哈
    不可相信
    服务端如果用控件数组,在vb中,它自动提供多线程
    两次的for不会交叉的
    当然,最好不要在for里面出现doevents
      

  19.   

    你把doevents去掉
    怎么同时发都是没问题的
    winsock本身有缓存,会解决着个问题的
      

  20.   

    TO  freedomjim(老头)    感谢您的回复,我使用的是winsock控件数组,我担心的是一个客户请求还没有处理完成(比如FOR循环还没有结束),服务端又有一个新的客户请求,这时可能结束上一个FOR循环,而开始了新的循环。我非常想知道您说的 “两次的for不会交叉的”的具体意思,请阁下指教!!    我的程序原形如下:http://www.cn700.com/Down_144/20041023141818.html请您看一下,是否会出现我说的问题,如果存在应该怎样更改?
      

  21.   

    详细看过你的程序
    其实,你就是害怕函数Public Function Message(UserCommand As String, Index As Integer)
    会出现你说的问题
    其实,你的担心是多余的
    一个请求如果在没有处理完,也就你说的,for还没结束,又来了一个请求,这是是否会停止上一个请求的for呢?!
    并不会,后面来的请求,winsock会自动给它们一个线程处理,当前线程照样处理第一个请求,直到处理完
    其实,这其中winsock已经把你的问题考虑进来了,当然,也不排除高并发量时的信息丢失,这个是因为winsock的缓存不搞,如果你的用户量不大,信息丢失一般不会发生
    如果你的用户量很大,象qq这样的超级服务器还是会发生的
      

  22.   

    其实,这其中winsock已经把你的问题考虑进来了,当然,也不排除高并发量时的信息丢失,这个是因为winsock的缓存不搞,如果你的用户量不大,信息丢失一般不会发生
    如果你的用户量很大,象qq这样的超级服务器还是会发生信息丢失的
    说明:qq是自己控制线程的<它的优点也在它的高并发>用户多了,什么事情都会发生
       以前的qq还是会丢失数据的,现在好些了
      

  23.   

    >>一个请求如果在没有处理完,也就你说的,for还没结束,又来了一个请求,这是是否会停止上一个>>请求的for呢?!
    >>并不会,后面来的请求,winsock会自动给它们一个线程处理,当前线程照样处理第一个请求,直到>>处理完错了!循环虽然不会停止!但winsock的DataArrival事件却不断发生.而你却还在循环里,不能取得数据!也因为winsock内有缓存,数据就积压在那了!而当你从循环里跑出来的时候,上一个DataArrival事件已经是N年前的事了!也就是说,Index被打乱了!
      

  24.   

    嗯.或许这个问题可以通过缓存的方法解决.也就是说,你在循环时,而DataArrival事件进行中.你可以用一个动态数组来保存着每次DataArrival所收到的数据.而当你从循环里出来的时候,再处理~
    很难想像,04发的数据,到05才收到是怎么一回事!哈哈~夸张了点!
    多线程有多线程出现在原因.不要企图打破,因为这是科学.
      

  25.   

    TO  freedomjim(老头)     非常感谢阁下的回复,我按照您说的方法做了,在FOR循环中去掉doevents,如果服务端接受到下一个用户的请求时,会形成一个WINDOWS消息队列,然后处理下一个客户的请求,但是如果客户的数量是10000或者是20000,VB6是单进程的只能一个一个的处理,这样的队列太可怕了,处在10000位置上的客户需要等待很久服务端才能处理他的请求,如何能够减少客户等待处理的速度?    如果在VB6中使用多进程也许可以解决这个问题,但是目前没有可以成功解决VB6多线程的成功案例,所以只能寄希望于尽一切可能降低客户等待服务端处理的速度,是服务端处理客户的请求加快!    如果您有更好的办法,万望指教!!非常感谢!!
      

  26.   

    to qyii(没读过大学)   我清楚您说的意思,但是目前没有可以成功解决VB6多线程的成功案例,所以只能寄希望于尽一切可能降低客户等待服务端处理的速度,使服务端处理客户的请求加快!   正如您说的如果10000个用户,服务端处理第10000个客户的请求时,可能需要等上一段时间,如何解决这个问题?目前我的程序已经写完90%,只能继续完成下去,不知道您是否有更好的解决方式?   多线程如何在VB6中成功的应用呢?
      

  27.   

    考虑的真长远呀,想到了10000-20000个客户端该怎么办,你遇到了吗?前面大家都说了那么多,你为什么不试试再说呢?纯理论分析有时会害人的!
    担心数据积压?先不考虑一台机器能不能容下10000个人在线,就算可以吧(反正我没敢想像过)。10000个人同时发消息任何机器都会堵呀(有这种可能吗?)再多线程,在CPU中还是一个个排队处理。
    一次循环给10000个人发消息要多长时间你试了吗?会很长吗?0.5秒钟之内,肯定结束!这种延时对网络通讯有影响吗?其实服务器1秒内给50000个客户端发消息也是能做到的。理论中也有出现大规模并发的概率之说呀,为什么这个你不借助于理论呢?总感觉你似乎在做一个能与QQ竞争的超大型系统,想在一台服务器上用VB实现QQ的所有服务器的能力。这一点在“理论”上是达不到!
      

  28.   

    TO homezj(小吉)》》其实服务器1秒内给50000个客户端发消息也是能做到的。
        您说的这一点我明白,但是“一次循环给10000个人发消息要多长时间你试了吗?会很长吗?0.5秒钟之内,肯定结束!”如果处在10000位置上的客户等待服务端处理他的请求,可能是10000*0.5=5000秒,这样的延迟太可怕了。我目前就是这个问题困扰我!!    如果我将vb6服务端的程序改写成vb.net是否可以解决我的问题?
      

  29.   

    10000个用户你为什么不用UDP来做呢,让两个客户端连上服务器后得到对方的IP和端口在让他们两个自己连,这样服务器的等待不就少了(自己没这样写过WINSOCK,只供思考有问题请提出)
      

  30.   

    to blackbug119(黑虫子)    如果使用UDP我担心遇到代理服务器,可能找不到对方用户。
      

  31.   

    》》其实服务器1秒内给50000个客户端发消息也是能做到的。
        您说的这一点我明白,但是“一次循环给10000个人发消息要多长时间你试了吗?会很长吗?0.5秒钟之内,肯定结束!”如果处在10000位置上的客户等待服务端处理他的请求,可能是10000*0.5=5000秒,这样的延迟太可怕了。我目前就是这个问题困扰我!!    如果我将vb6服务端的程序改写成vb.net是否可以解决我的问题?
    ==================================================================
    vb的winsock的苏组的index是1个inter 类型,只支持32767个用户,因此不会出现,也不能支持50000用户,要想支持那么多,只有采用udp
      

  32.   

    to zyg0(影子(转了1圈,我又回来了)    50000用户只是打一个比方。如果处在10000位置上的客户等待服务端处理他的请求,可能是10000*0.5=5000秒,这样的延迟太可怕了。我目前就是这个问题困扰我!!    各位有什么好的方法?  如果我将vb6服务端的程序采用.NET的无缝升级,升级为vb.net是否可以解决我的问题?
      

  33.   

    其实你如果采用的是tcp和winsocket苏组的话,他的内部其实是多线程的,1个控件相当于1个线程
    不用担心什么延时,只要配置高的网络带宽和机器性能就行了
      

  34.   

    如果我将vb6服务端的程序采用.NET的无缝升级,升级为vb.net是否可以解决我的问题?
    根本不存在无锋升级,那只是微软的神话,不可能的,你几乎代码都需要从写
      

  35.   

    to  zyg0(影子(转了1圈,我又回来了)     看了您刚刚的回复,我深感安慰。谢谢!我采用的是tcp和winsocket数组,我希望您能够看一下我的程序,但是我始终担心,vb6单线程会阻碍winsocket数组的多线程,因为我的FOR循环不知道写的是否正确,比如服务端的函数Public Function Message(UserCommand As String, Index As Integer)
    。结果是否会产生严重的客户等待信息返回(延时)?我的程序原形如下:http://www.cn700.com/Down_144/20041023141818.html
      

  36.   

    实在是不好意思,我现在在转.net,正在学习中,没有时间看你的程序的,不好意思,
      

  37.   

    3万个用户我担心有问题,因为苏组的索引是32767你想吧,你必须预留1半来避免突发的事件,个人认为,没有经过实践,因为也没有环境测试,10000个的话要是配置购得话应该能跑起来,过万的话就不要 用vb了,最好是c
    vb保证3000-5000同时在线应该没问题
      

  38.   

    10000*0.5=50000? 这是什么逻辑?0.5秒之内就全部循环完了,哪怕你就是那第10000个客户端,也最多延时0.5秒呀!!!!这种群发也并不是每时每刻都要做的,偶尔出现而已。你总担心什么?强烈建议你动手试试,光谈是没用的,
    1、Tcp连接的服务器不太可能支持到10000的;
    2、能有几千个客户,一般不会明显感觉到延时的;
    何况别人QQ给你发来的消息,可能也是几秒前就送到服务器了呢,排队了几秒才发到你这的,网络传输有点延时是很正常。设计时考虑一点误差就够,没你想像那么严重,凭空想像写程序,这种习惯很多不好。总之:你这种担心是多余,要相信,CPU远比你想像的要快得多!你从1数到10000可能要10000*0.5=50000秒,但电脑会在你还没张口前就办到了。
      

  39.   

    TO  homezj(小吉)    谢谢您的回复!    如果我将用户数量控制在4000以内,不管收到多长的windows消息队列,然后交给vb一个一个的执行,vb的处理也会迎刃有余,延迟也不会让人无法忍受,是吗?
        
      

  40.   

    晕死 vb6和vb.net一个是winsock组件 一个是system.net.socket空间 都是封装好的阻塞模式 只不过用.net 你要自己开线程而已 根本没意义 如果用直接升级到.net 只不过把winsock封装成了.net的dll而已 代码也改了 确实能运行 不过毫无意义
    只要用户没有500以上同时进行连接请求 winsock应该没问题 维持长连接3000也不成问题 
    消息广播如果用的地方太多 可以考虑udp作为补充 凡是udp发过去 没回应包的 就再用tcp发一次就可以了 UDP可以用组播嘛
      

  41.   

    这是切身感受!你认为不是我也没办法!我的CPU,AMDXP2200.的确是个很慢的东东!
      

  42.   

    有空看看他吧:http://community.csdn.net/Expert/topic/3652/3652431.xml?temp=.4773218