大讨论:关于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个线程里面,各自处理各自的不存在谁先谁后的问题,每个请求都能得到及时的处理。
所以必须要用多线程来做,至于同时可以有多少客户端连接,这就取决于你的服务器性能了。
[解决办法]
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 SubPrivate 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 SubAttribute VB_Name = "SockStruct"Public Type Sockets Index As Integer RequestID As Long Connect_IP As StringEnd TypePublic Type stackelem Index As IntegerEnd TypePublic Sock(399) As SocketsPublic stack(399) As stackelemPublic s_top As IntegerPublic s_base As IntegerPublic Number As IntegerPublic stack_empty As stackelemPublic Function StackEmpty() As Boolean If Number = 0 Then StackEmpty = True Else StackEmpty = False End IfEnd FunctionPublic Function init_stack() Number = 400 s_top = 400 s_base = 0 For i = 0 To 399 stack(i).Index = i NextEnd FunctionPublic Function push(elem As stackelem) '由于只限制400 连接 不会出现三益出 stack(Number) = elem Number = Number + 1 s_top = Number End FunctionPublic Function pop(elem As stackelem) elem = stack(s_top - 1) Number = Number - 1 s_top = Number End Function
[解决办法]
数量超过1000还是用 完成端口(IOCP)方式
无论使用哪种方式, 都要使用连接池
初始化时系统就准备好一系列的连接Socket, 或放在数组中, 有客户连接从再有的未数组中找出没有空闲的做对映
[解决办法]