1.
Client 连接Server后,进行数据发送,如果发送的数据量很大,那么所需要的时间就比较长,如果此时又有一个Client要求连接Server,那么在server端的connectionrequest事件中的代码
if winsock1.state<>sckclosed then winsock1.close
就关闭了正在接收数据的连接而同新出现的连接请求作出响应,这样原来正在连接发送数据的client端就被关闭了,服务器端的所收到的数据就不完整了.问这个问题,可能是因为对网络原理:tcp/ip方面没有做到深切了解和对winsock控件还不熟悉的原因了,所以又产生了这样的念头:
是不是winsock控件可以同时开很多的连接来应付多个client的连接请求
如果是这样的话,又多出了一个疑问:
     服务器端假设使用的端口为:winsock1.localPort=2001
     也就是说server同时面对多个client的请求connect,listen,sendata,getdata,这样端口会不会出现应付不了的局面?
2.在网络原理中曾经学过滑动窗口这些内容,发送端在发送数据的时候,是把要发送的数据分为很多很多的数据块,然后在tcp/ip模型中往下层逐层打包,然后发送的,而且为了接省接收到接收端的wait时间,发送端是会不停地发发送这些数据小块的.我就假设接收端全部顺利接收到了这些小数据块到缓冲区内.那么想问的是,接收不是要等待到这些数据块全部到齐了,并按照原来的顺序重新排序组合好后,winsock1.getdata方法才会生效?不然的话,接收端在dataarrial事件中的getdata永远不会生效??3.如果server是关闭的,那么所有的client不管它怎么连接都会无法连接到server上去,这样client端要一直连下去吗?在这里不需要控制一下连接的时间吗?我知道winsock控件上有个state属性里面是有一系列的枚举值如:sckclosed,sckopen,sckListening==,是不是就是利用这些属性来控制客户端的连接时间?能给出一些时间值作为参考吗?如:client的connect请求发出多久后还没接收到ack就会重新发送connect请求?在重新发送多少遍后还没收到ack就会挂起?呵呵,凭着有限的知识在猜测,猜测是不是这样就请你们来讨论一下.4.各个client对server发出了,要求server发送数据的请求,是不是利用winsock1.remotehostip来发送数据各个来自不同地方的client??还是在练习使用winsock控件就遇到了一大堆问题,望指教

解决方案 »

  1.   

    1 用控件数组
    winsock(i)
      

  2.   

    窗口添加一个winsock控件,设index属性为0 ------建立控件数组Private Sub sckServerAll_ConnectionRequest(Index As Integer, ByVal requestID As Long)    Dim i As Long
        
        For i = 1 To OnLineUserMax
          Dim k As Integer
          k = sckServerAll(i).State
          If sckServerAll(i).State = 0 Then GoTo frmMain_ert  '判断是否有空闲Winsock控件
          If sckServerAll(i).State = 3 Or sckServerAll(i).State = 8 Or sckServerAll(i).State = 9 Then
             sckServerAll(i).Close
             GoTo frmMain_ert
          End If
        Next i
        OnLineUserMax = OnLineUserMax + 1              '当前用户数
        ReDim Preserve OnLineUser(OnLineUserMax)       '增加一个用户信息数组,存储用户信息用
        i = OnLineUserMax
        Load sckServerAll(i)           '动态增加一个Winsock控件数组
        
    frmMain_ert:
       sckServerAll(i).Accept requestIDEnd Sub
      

  3.   

    先谢谢兄弟了
    你的意思是一个winsock控件只建立一个连接了
    代码偶不需要,先明确一下而已
    第一问的答案就如兄弟所说的一样,一个winsock一个连接,那也应该使用动态数组了
    当新的连接请求出现的时候,先检查原来的winsock控件的state,闲的话就直接利用它来应答新的请求,如果忙的话就load了,数组动态加一
    呵呵,简单的思路而已,不知道能否实现
    还请楼下的多多指点
      

  4.   

    作一些解释,希望能帮助你理解上面的程序:
    1. 每一个Client的连接,在Server端都有一个Socket(即上面程序中的sckServerAll(1)至sckServerAll(OnLineUserMax))与之对应。这些Socket的LocalPort肯定不等于(也不可以等于)侦听端口号。
    2. 除了这些Socket之外,Server端还有一个只用于侦听而从来不会和Client建立真正的连接的
    Socket(即上面程序中的sckServerAll(0)),它的LocalPort就是侦听的端口号。
      

  5.   

    对于问题1,1楼的回答是正确的。
        补充一句,断口开的多了不会处理不了,如果你用WIN98那么就惨了,WIN98的单个程序最多开80多个端口,而WIN2K或WINXP都没有这种限制,我曾经最多开过4000多个端口,确实处理比较慢,但并不是处理不了,因为,每个端口都要发送、接收并且大量的计算,而我的CPU太弱,所以才慢,而且慢的结果就是经常掉线。对于问题2:    a、如果你的数据是分段发送的话:
           1、当你的段比接收端的缓冲区小的时候,那么你的每次发送,接收段都会产生一次DataArrival事件;
           2、如果你的段比接收端的缓冲大,那么接收段只要接收到缓冲满就会产生一次DataArrival事件。
        b、我们完全可以只讲接收端作分段接收处理,因为发送端的WinSock驱动会替你自动分段,其实WinSock驱动的接收端从来都是替你自动分端的,只不过是我们在编写程序的时候基本上都是上述a中描述的情况1,所以我们会误认为,我们自己必须分端处理。对于问题3:    WinSock控件还有一个事件是Error事件,如果在指定的时间内(WinSock的超时属性)没有连接成功就会产生这个事件,你只要判断Error事件中的Number=10061(Description="连接被强制拒绝")就说明,服务器没有开启侦听端口,而你利用模块级变量设置一个计数器:
         IF 程序启动或连接成功 Then 计数器=0
         IF 连接被强制拒绝 Then 计数器=计数器+1
         IF 计数器<n Then 重新连接
        这样就可解决你的问题3。对于问题4:
        问题1解决了,那么问题4就应该解决了。因为1楼的答案是正确的,而你的控件数组中的每个控件只连接1个确认的客户端,所以通过这个数组中的某个控件就可以直接用该控件的SendData将数据发送到指定客户端上,而你并不需要了解那些客户的IP和Port。
      

  6.   

    呵呵,就是说一个client端的ClientWinsock对应于一个Server端的ServerWinsock了
    而数据的分段发送会由winsock控件的驱动程序来自动完成,只要连接成功数据的发送和接收是自动完成的了.
    如果客户端太多,使用控件数组的话,总觉得开销太大了
      

  7.   

    jadeluo(秀峰) 
    作一些解释,希望能帮助你理解上面的程序:
    1. 每一个Client的连接,在Server端都有一个Socket(即上面程序中的sckServerAll(1)至sckServerAll(OnLineUserMax))与之对应。这些Socket的LocalPort肯定不等于(也不可以等于)侦听端口号。
    2. 除了这些Socket之外,Server端还有一个只用于侦听而从来不会和Client建立真正的连接的
    Socket(即上面程序中的sckServerAll(0)),它的LocalPort就是侦听的端口号。
    你的2我有点不明白偶看了好几个简单的例子:
    server端的
    Private sub Form_Load()
      sockserver(1).localport=2000
      sockserver(1).listen
    End Sub
    1那么sockserver(1).localport=2000这个端口不就是要负责侦听,发送数据,接收数据的工作吗?2是不是一个winsock控件只对应使用一个端口?还是winsock数组里的所有控件都可以使用相同的端口,估计应该是一个winsock使用一个端口的了,因为有个.localPort=0,来让它随机选择,请你们确认一下
      

  8.   

    用一个Socket负责侦听,当有Client请求连接时(即发生ConnectionRequest事件时),用另外的Socket去接受这个连接请求(Accept),而负责侦听的Socket继续侦听。以上就是单个端口号同时连接多个Client的原理。
      

  9.   

    给你个小例子:
    Option Explicit'此窗体中需要一个Winsock控件, 名为sckServer, Index属性值为0
    '还需要一个TextBox控件, 名为txtTestDim iCurrentClient As IntegerPrivate Sub Form_Load()
        sckServer(0).LocalPort = 8000
        sckServer(0).Bind
        sckServer(0).Listen
        iCurrentClient = 1
    End SubPrivate Sub Form_Unload(Cancel As Integer)
        sckServer(0).Close
        End
    End SubPrivate Sub sckServer_ConnectionRequest(Index As Integer, ByVal requestID As Long)
        Load sckServer(iCurrentClient)
        sckServer(iCurrentClient).Accept requestID
        iCurrentClient = iCurrentClient + 1
    End SubPrivate Sub sckServer_Error(Index As Integer, ByVal Number As Integer, Description As String, ByVal Scode As Long, ByVal Source As String, ByVal HelpFile As String, ByVal HelpContext As Long, CancelDisplay As Boolean)
        If sckServer(Index).State <> sckClosed Then sckServer(Index).Close
    End SubPrivate Sub sckServer_DataArrival(Index As Integer, ByVal bytesTotal As Long)
        Dim sData As String
        sckServer(Index).GetData sData, vbString
        txtTest.Text = sckServer(Index).RemoteHostIP & ":" & sckServer(Index).RemotePort & " - " & _
                       sData & vbCrLf & txtTest.Text
    End Sub
    注:此例子中未对动态加载的WinSock的数量进行判断, 在第32768次连接时会出现错误。
      

  10.   

    楼上给出的参考代码,最好还可以动态unload  winsock控件,这样就当服务器程序一直运行的时候不会出错了