首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > VB >

大议论:关于VB Winsock

2013-01-01 
大讨论:关于VB Winsock。近来用到了winsock,有些地方钻研不够深入,所以想与各位讨论一下。在VB中,服务器的wi

大讨论:关于VB Winsock。
近来用到了winsock,有些地方钻研不够深入,所以想与各位讨论一下。
在VB中,服务器的winsock瞬间的连接量大概在三四十左右。也就是说,同一秒内,有三四十个客户端连接到服务器,因为使用的是tcp,所以就使用了winsock的控件数组,有多少个连接就建立多少个winsock。请问,如果这个瞬间的连接量再大很多的话,服务器能不能承受?比如说1000或者更多。
当然,这个瞬间的连接量只是服务器程序刚刚启动时才有的,因为客户端是有限的,所以就现在的情况来看,最大的连接数是100.
因为以后要增加客户端,所以在服务器程序打开的时候,客户端就会一起对服务器进行连接,这个连接时很快的,在服务器开始的一两秒内,就会有1000甚至更多的Tcp进行连接,服务能不能承受?
[解决办法]
从控件的角度来看,只要用于分配应答ID的那个控件在成功分配一个请求到另一WINSOCK控件之间的时间内,没有新的请求到来即没有问题

但是这个不太好测试,要构建的环境不容易得到.

楼主如果是为了保证连接的可靠性,那么可以从流程上进行优化,即客户端在连接时增加超时与重试机制,这样只要网络没问题+服务器端程序没问题,就一定可以处理完所有的请求.

比如一秒内并发1W个请求,但服务器端程序最多只能在一秒内应答1000个,那么假设客户端重试为3秒一次,则最坏的情况是27秒左右处理完所有请求.

由于服务器端处理能力有限,速度肯定慢下来了,但这样至少能保证全部请求的处理.
[解决办法]
必须用多线程。

假定服务器处理一个请求需要10毫秒的话,不用多线程处理1000个请求需要10秒钟的时间,按照每秒钟有1000个请求,10秒钟就有1W个请求,那么就有9000个请求得不到及时处理,用不了几分钟你的系统就完蛋了。

用多线程的话1000个请求被分到了1000个线程里面去处理,1W个请求被分到了1W个线程里面,各自处理各自的不存在谁先谁后的问题,每个请求都能得到及时的处理。

所以必须要用多线程来做,至于同时可以有多少客户端连接,这就取决于你的服务器性能了。
[解决办法]

引用:
必须用多线程。 

假定服务器处理一个请求需要10毫秒的话,不用多线程处理1000个请求需要10秒钟的时间,按照每秒钟有1000个请求,10秒钟就有1W个请求,那么就有9000个请求得不到及时处理,用不了几分钟你的系统就完蛋了。 

用多线程的话1000个请求被分到了1000个线程里面去处理,1W个请求被分到了1W个线程里面,各自处理各自的不存在谁先谁后的问题,每个请求都能得到及时的处理。 

所以必须要用多线程来做,至于同时可以…



如果用多线程,再使用winsock控件,那么可以这么肯定的告诉你,在VB6.0的环境下,一定出错,如果真需要这么做,那么LZ必须
用API重写sock自带的一些功能

至于LZ说系统会因为sock连接量,而完蛋,这.....  微软的东西不是豆腐渣.

不存在LZ所说的承受不承受得了的问题,,这取决于你的硬件设备,和winsock无关.
[解决办法]
1、不要使用多线程,否则你会死得很惨,因为你是VB来开发,而不是VC;
2、我曾经参加过一个项目,是关于出租车GPS连接的。刚开始时有1000多个车台要登录到服务器上,并且每个车台在一分钟之内要上发一条消息到服务器上(每条消息大约150个字符),没有出现过数据丢失的现象。后来扩展(增加车台的数量),一直到现在都没有出现问题。但是需要强调的是,在连接丢失后,要自动地将废弃的socket对象释放,并保证能够被重新分配给新的连接(原因是:A.没必要维护不用的socket对象;B.控件数组的index为integer对象,如果不循环使用,小心会溢出)。
[解决办法]
引用:
从控件的角度来看,只要用于分配应答ID的那个控件在成功分配一个请求到另一WINSOCK控件之间的时间内,没有新的请求到来即没有问题

我的问题就出在这里,在分配应答ID的那个控件在成功分配一个请求到另外一个WINSOCK控件之间的时间内,又有新的请求,这样是不是会出现阻塞的现象啊,那么就会有丢失的现象呢?我做了个重连函数,但是那么多的阻塞申请里面如果还是在那个时间内,又会出现阻塞,所以我从ConnectionRequest事件和DataArrival时间里面都做了标记,响应的次数和dataarrival 的次数有的时候会有很大的差别的
[解决办法]
引用:
LZ可以去看IOCP原理,不过用vb做,即使可以用完成端口,估计也没什么效率...

用SocketMaster可能要好点


我用VB也做了个多连接服务端,测试1W连接数,效率还行。这个不是因为用什么语言而导致效率降低,而是因为需要消耗的系统资源多,而你机器又不够快而导致的“效率”低,不信你用VC写个同样的程序看看,要不然你以为各大网络游戏服务商为什么整天没事就升级服务器呢?是他们的服务端“效率”不行?有些东西啊,不能想当然,你想一步登天是不可能的,饭都是一口一口才能吃下去的,照这样说吃饭这个问题也算是“效率”问题。
[解决办法]
引用:
从控件的角度来看,只要用于分配应答ID的那个控件在成功分配一个请求到另一WINSOCK控件之间的时间内,没有新的请求到来即没有问题

但是这个不太好测试,要构建的环境不容易得到.

楼主如果是为了保证连接的可靠性,那么可以从流程上进行优化,即客户端在连接时增加超时与重试机制,这样只要网络没问题+服务器端程序没问题,就一定可以处理完所有的请求.

比如一秒内并发1W个请求,但服务器端程序最多只能在一秒内应答1000个,那么假设客户端重试为3秒一次,则最坏的情况是27秒左右处理完所有请求.

由于服务器端处理能力有限,速度肯定慢下来了,但这样至少能保证全部请求的处理.


还是老马看的透彻,不过老马你这个考虑的“同时”就不是一般正常运用的问题了,“同时”有1W个并发的话,这个就不是正常的客户端运用了,那就是是"DDOS"攻击了,关于“DDOS”与这个并发我也不多说。不过VB做的服务端可以“同时”处理1~2百个连接是不成问题的,就像老马说的,这个测试环境有点难以构建,因此我想了另一个折中的办法,编写了一个“同时”进行数千个连接请求发送的客户端,在3台电脑上运行,“同时”向服务端发送登录请求,我测试了每个服务端程序使用1500个并发连接,每台电脑运行3个客户端,服务器也在30多秒内就处理完了。这个应该可以证明点事情了吧。虽然测试环境和“DDOS”相去甚远,但是据我所指,目前还没有有效防御“DDOS”攻击的手段啊,这个就不是VB和VC的问题了。
------解决方案--------------------


Winsock控件的index属性本来就是个安全的多线程,在很多时候,也有很多人用纯API来自构SOCK应用层,但一般都过不了index这关,别小看这个多线程,如果自己用VB6 API自已写,这个就是最大的问题.

如果在同一时间点,连接数大于Index这个数,那么也不是没办法,当在load sock时发现state都为连接状态则winsock1肯定会报错,在ERROR事件捕捉这个情况,用winsock2反连客户端,告诉客户端新的端口号,客户端根据新的端口号重连服务器端,当然,一般都不会让客户端重连服务器,一般在客户端都会提示用户:连接数已满,您正处于排队中,在您前面还有X个用户.

但上面的情况,一般来说会碰到的情况机率不高,除非你做大型网络平台(比如网络游戏),那么可能在同一时间点,连接数大于32766,
[解决办法]
楼上的,vb.net,和vb差不多
用vb.net写个多线程的Winsock监听
我的程序是这么实施的,服务端没有用vb写,
默认最大连接数是3000个(同一时间),也就是说最大线程是3000个.(连接数个人设置的)
每个线程自动处理数据.如果连接数超过3000,服务端可以设置,[超过最大连接数是否重启]服务端(exe)
开100个线程,服务端不超过40M内存,CPU影响不大
[解决办法]

引用:
1、不要使用多线程,否则你会死得很惨,因为你是VB来开发,而不是VC;
2、我曾经参加过一个项目,是关于出租车GPS连接的。刚开始时有1000多个车台要登录到服务器上,并且每个车台在一分钟之内要上发一条消息到服务器上(每条消息大约150个字符),没有出现过数据丢失的现象。后来扩展(增加车台的数量),一直到现在都没有出现问题。但是需要强调的是,在连接丢失后,要自动地将废弃的socket对象释放,并保证能够被重新分配给新的连接(原因是:A.没必要维护不用的socket对象;B.控件数组的index为integer对象,如果不循环使用,小心会溢出)。

vb可以转vb.net,应该易如反掌,至少我做到了
转C++ socket多线程,我也做到了...
不要局限于语言,而导致生存率低下,其实有空看看<<人月神话>>
你说的溢出只是index值的问题
建议使用多线程,给自己的程序一个最大可能的空间
如果因公司业务增加,客户端达到1k,10k,怎么办....你不得不放弃控件数组
重新编码,这个时候的问题,只有你自己可想而知了,是谁来处理
[解决办法]
vb可以转vb.net,应该易如反掌,至少我做到了 
转C++ socket多线程,我也做到了... 
不要局限于语言,而导致生存率低下,其实有空看看 < <人月神话>> 
你说的溢出只是index值的问题 
建议使用多线程,给自己的程序一个最大可能的空间 
如果因公司业务增加,客户端达到1k,10k,怎么办....你不得不放弃控件数组 
重新编码,这个时候的问题,只有你自己可想而知了,是谁来处理
[解决办法]
http://d.download.csdn.net/down/176593/CNCPT01

以前用 VB 时候写的 四国军棋.未完善,但是里面用到了 WINSOCK ,里面的客户端连接处理机制还是可以供参考的~


Private Sub Sock_TCP_Close(index As Integer)
    '将关闭的连接对应的用户 状态清0 除非已经在线。
    Dim elem As stackelem
    If index = 0 Then
        MsgBox "a"
    Else
        Unload Sock_TCP(index)
        elem.index = index
        push elem
    End If
    With Sock(elem.index)
        .index = elem.index
        .RequestID = 0
        .Connect_IP = ""
    End With
        
End Sub

Private Sub Sock_TCP_ConnectionRequest(index As Integer, ByVal RequestID As Long)
    
    Dim tmp_index As Integer
    Dim elem As stackelem
    
    If StackEmpty <> True Then
        pop elem
    End If
        'MsgBox Sock_TCP(0).State
        Load Sock_TCP(elem.index)
        
        PRINTMSG "Connection  Request!"
        



        If Sock_TCP(elem.index).State <> sckClosed Then
            Sock_TCP(elem.index).Close
        End If
        
        Sock_TCP(elem.index).Accept RequestID
        PRINTMSG "Current Connection Accepted By Sock:" & CStr(elem.index) & "!"

        With Sock(elem.index) '11/5 突然觉得这个结构现在没用,,,,
            .index = elem.index
            .RequestID = RequestID
            .Connect_IP = Sock_TCP(elem.index).RemoteHostIP
        End With
        
        CountNum = CountNum + 1
        PRINTMSG "Current Connection Comes From:" & Sock_TCP(elem.index).RemoteHostIP '为了简单起见放在这 严格上说 这样描述并步正确!
        PRINTMSG "Current Connections:" & CStr(CountNum)
    
End Sub


Attribute VB_Name = "SockStruct"
Public Type Sockets
     Index As Integer
     RequestID As Long
     Connect_IP As String
End Type

Public Type stackelem
    Index As Integer
End Type

Public Sock(399) As Sockets
Public stack(399) As stackelem

Public s_top As Integer
Public s_base As Integer
Public Number As Integer
Public stack_empty As stackelem


Public Function StackEmpty() As Boolean
    If Number = 0 Then
        StackEmpty = True
    Else
        StackEmpty = False
    End If
End Function

Public Function init_stack()
    Number = 400
    s_top = 400
    s_base = 0
    For i = 0 To 399
        stack(i).Index = i
    Next
End Function

Public Function push(elem As stackelem)
    '由于只限制400 连接 不会出现三益出
    stack(Number) = elem
    Number = Number + 1
    s_top = Number
    
End Function

Public Function pop(elem As stackelem)
    
    elem = stack(s_top - 1)
    Number = Number - 1
    s_top = Number
    
End Function



------解决方案--------------------


数量超过1000还是用 完成端口(IOCP)方式
无论使用哪种方式, 都要使用连接池
初始化时系统就准备好一系列的连接Socket, 或放在数组中, 有客户连接从再有的未数组中找出没有空闲的做对映

[解决办法]

引用:
各位啊,草民有一个问题:
用vb6winsock做通讯,服务端用winsock数组对应各个客户端。
那么这些数组它们是各自有一个端口号呢还是共用一个端口号?
曾试过这两种情况,均不能实现群通讯?不知为什么?


使用TCP协议,客户端和服务端都使用同一个端口,服务端使用一个sock进行侦听 sock.Listen 方法 ,使用另一个控件数组响应请求,在sock__ConnectionRequest(ByVal requestID As Long) 事件中,使用Sock1(SockIndex).Accept (requestID) 方法接受客户端连接请求。这时 Accept 方法会自动分配端口给客户端用,而你不用考虑这个自动分配的端口号,这个是由winsock控件自动管理的,你只需要保证客户端设置的通讯端口和服务端的侦听端口相同即可。

热点排行