我用vb做客户端,winsock数组做中间层,access做数据库。现在问题是这样,客户端用winsock向服务器上的winsock发送ckIP查询命令,服务器上的winsock(0)监听,然后动态生成数组并接收客户端的ckIP命令,然后调用ckIP_sub过程,ckIP_sub查询数据库,再将查询的结果返回给服务器上的winsock(数组),然后服务器上的winsock(数组)再返回给客户端winsock。
出现的问题是,在服务器端收到ckIP命令,并调用ckIP_sub过程查询数据库的过程中,如果有另一个客户端b登陆的话,那么ckIP_sub查询的结果就会被返回到这个最后登陆的客户端b上,请问是怎么回事?
下面是相关部代的代码:客户端发送命令的代码:
'发送数据
Private Sub SendDate()
Dim cinfo
cinfo = "请求检查客户端IP"
sock.SendData cinfo
StateInfo.Caption = "正在向服务器请求验证IP..."
End Sub服务器端接收命令并调用ckIP_sub过程的代码:
'接收用户数据并根据信息字符串来判断是什么命令而调用相关的过程
Public Sub Sock_DataArrival(Index As Integer, ByVal bytesTotal As Long)
Dim cinfo As String
Dim svrinfo As String
Text1.Text = "数据来自序列:" & Index & ", IP:" & Sock(Index).RemoteHostIP
Sock(Index).GetData cinfo  '取得客户端发送的信息
If cinfo = "请求检查客户端IP" Then  '判断是什么命令
Text1.Text = "客户端请求检查用户:" & Index & ",的IP:" & Sock(Index).RemoteHostIP & "是否合法"
Call ckIP_Sub '调用模块中的IP检测过程
End If
End Sub模块中ckIP_sub的代码:
Public Sub ckIP_Sub()  '查询语句
Call LinkDB_Sub
rs.Open "select * from ipusers where ipaddress='" & Form1.Sock(Index).RemoteHostIP & "'", cn
If Not rs.EOF Then
ckIP_res = True
svrinfo = ckIP_res
MsgBox svrinfo
Form1.Sock(Index).SendData svrinfo
Form1.Text1.Text = "已返回数据至用户:" & Index & ", IP:" & Form1.Sock(Index).RemoteHostIP
Else
ckIP_res = False
svrinfo = ckIP_res
MsgBox svrinfo
Form1.Sock(Index).SendData svrinfo
Form1.Text1.Text = "已返回数据至用户:" & Index & ", IP:" & Form1.Sock(Index).RemoteHostIP
End If
'Form1.Label1.Caption = rs.GetString
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing
End Sub
请问上面代码中,是哪个地方造成服务器将查询结果发送到了最后登陆的客户端上?

解决方案 »

  1.   

    这段代码的问题在于,模块ckIP_sub中的INDEX,和Sock_DataArrival获取的参数INDEX之间其实没有任何关系。所以,你收到消息的是一个SOCKET控件,而发送消息的是另一个SOCKET控件。正所谓,此INDEX,非彼INDEX也。
      

  2.   

    调试时不要在一台机器开两个客户端,如果只是检查IP是否合法的话可以在ConnectionRequest事件中检查,
       Private Sub ServerSock_ConnectionRequest(Index As Integer, ByVal requestID As Long)
        On Error Resume Next
        UserIp = ServerSock(0).RemoteHostIP '获得登录者的IP地址
        i = 1
        Do While i <= ServerSock.UBound '检查是否已经有该地址的记录
            If ServerSock(i).RemoteHostIP = UserIp Then '如有,不必加载新的控件
                ServerSock(i).Accept requestID
                Exit Sub
            End If
            i = i + 1
        Loop
        '如果还没有此IP的连接成功记录,在这里先建立连接再判断是否是合法IP!
        '不是的话   再退出这个过程,不接受这个requestID,
    '################################################################
    '以下代码是你的,没细看要,      想实现返回提示错误信息应该是先Accept requestID,发送错误提示信息,再关闭此连接吧
        '是的话
        Load ServerSock(i)
        ServerSock(i).Accept requestID
    End Sub
      

  3.   

    我觉得现在编程工具就是一个超级浏览器。设计三层结构可以用以下方法来解决。用VB+WEBSERVERS来解决。客户端用VB的XML对象来解决。服务端可以用ASP来解决。这里的ASP不是我们设计网页的那种。这里我们关心的数据。不是网页界面。所以放回的结果是一个XML文档。然后通过VB的XML Request来获取这个XML数据。如果要更新记录。就POST XML数据文件到服务器,再用ASP处理。这样就不用Winsock来处理拉。因为WinsoCK要控件的支持。而XML是一个标准。不需要控件支持。
      

  4.   

    1、先说你的问题,需要在服务器上使用添加新的对象来指定接收的对象, Load ServerSock(i)    ServerSock(i).Accept requestID这样就不会发错了。
    2、你的这样三层结构,我还是有点担心,你可以向服务器发送sql语句,但返回的rs记录集,你的中间层怎么处理发送,你的应用层怎么实现获取记录集。
      

  5.   

    创建Socket多客户服务器 
    1.设定端口号、开始侦听 2.接收客户连接请求 
    3.接收、发送数据 4.响应客户关闭、主动关闭连接 
     
    设定端口号、开始侦听
     
    我们可以使用控件数组创建多客户服务器,达到多个客户同时连接到服务器。
    向窗体增加一个WinSock控件,修改其Name属性为SockServer,修改Index属性为0。
    在窗体的Load事件中增加如下代码:
    SockServer(0).LocalPort=2000
    SockServer(0).Listen
    数组控件0始终处于侦听状态。 
    接收客户连接请求
     
    在ConnectionRequest事件中首先加载一个Socket控件,再用它来接收连接。
    Dim SockNum As Integer
    SockNum=0
    Sub SockServer_ConnectionRequest(...)
    SockNum=SockNum+1
    Load SockServer(SockNum)
    SockServer(SockNum).Accept requestID
    End Sub 
    接收客户发送的数据 和 向客户发送的数据
     
    接收客户发送的数据
    在DataArrival事件中将多一个Index参数,用于表示哪一个控件接收到了数据。
    Sub SockServer_DataArrival(Index As Integer,ByVal bytesTotal As Long)
    Dim s As String
    SockServer(Index).GetData s
    End Sub 
    向客户发送的数据
    哪一个控件需要发送,只需加上数组下标。
    SockServer(n).SendData Text1.Text 
    响应客户关闭 和 主动关闭连接
     
    响应客户关闭
    同样在Close事件中也会增加Index参数表示哪一个连接关闭。
    Sub SockServer_Close(Index As Integer)
    SockServer(Index).Close
    End Sub 
    主动关闭连接
    哪一个连接需要主动关闭,只需增加数组下标。
    SockServer(n).Close
      

  6.   

    根据你所说的情况,应该维护一个消息队列。
    当server端对A的请求没有完成时,其他client发来的消息都应该进入到队列中等候;当server端对A的请求处理完成时,因该到消息队列中得到下一个处理任务(即排在A机器后的请求或是优先级别高的请求),如此循环处理消息队列中的任务,直到空为止。这样才能明确你的处理逻辑,否则过于混乱,不利于维护。
    队列可以用数组或是collection来维护,循环访问队列可以用timer来实现。
    以上仅供参考。:)
      

  7.   

    问题在于SOCK数组序列号上.两个过程的INDEX是不一样的.
    可以设置一个参数sckindex为全局变量
    sock(sckindex)这样sckindex可以在下面的过程使用
      

  8.   

    在调用ckIP_Sub的时候,直接把Index也传过来就可以达到两处Index一样了嘛