标题:VB如何建立多人通信
只看楼主
leziyi
Rank: 1
等 级:新手上路
帖 子:52
专家分:0
注 册:2016-10-30
结帖率:85.71%
 问题点数:0 回复次数:15 
VB如何建立多人通信
Public Function FindFreeSock(SockName As Winsock)

Dim i

For i = 0 To SockName.Ubuod

    If i = SockName.Uboud Then
   
       Load (i + 1)
      
    End If

    If SockName(i).State = 0 Then
   
       SockName(i).Listen
      
    End If
   
Next

End Function
---------------------------------------------------------
Private Sub Command1_Click()

If Text1.Text = "" Then

   MsgBox "请输入IP地址!"
   
   Exit Sub
   
ElseIf Text2.Text = "" Then

   MsgBox "请输入监听端口!"
   
   Exit Sub
   
End If

FindFreeSock (Socket)---------------------------------此行出错

With Socket

     .RemoteHost = Text1.Text
     
     .RemotePort = Text2.Text
     
End With

Socket

With Sock

     .RemoteHost = Text1.Text
     
     .RemotePort = Text2.Text
     
End With

Sock.Connect

Picture1.Print "正在连接......"

End Sub
搜索更多相关主题的帖子: If End Sub Text With 
2018-10-27 11:32
沉默的痞子
Rank: 4
等 级:贵宾
威 望:12
帖 子:96
专家分:127
注 册:2015-10-7
得分:0 
FindFreeSock (Socket)  改成
call FindFreeSock (Socket)  
2018-10-27 14:45
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
得分:0 
局域网的通讯比较容易,就使用winsocket控件udp协议完成,互联网的通讯则麻烦些,需要一个公网地址,由公网服务器连接各客户端,用tcp/ip协议将通讯内容逐个转发,当然也可以由公网服务器递交通讯双方的ip和端口号,用udp协议打洞点对点通讯。

能编个毛线衣吗?
2018-10-28 10:13
紫苑星苑
Rank: 2
等 级:论坛游民
威 望:2
帖 子:12
专家分:42
注 册:2018-9-2
得分:0 
我就分享一下我所研究的TCP的多人通信(半成品ing)
首先需要一个用来接收和发送处理所有数据的服务端:
而且服务端的Winsock控件必须是控件组.即将Winsock的index值设为0

所需控件:
1.两个List,一个命名为report(用来记录链接情况以及其他人的消息),一个命名为LinkClient(用来记录所有链接的人)
2.一个Text,命名为Command(用来发送消息)
3.一个Winsock,命名为ServerLink(index值设为0)
然后首先在全局部分定义一个全局变量:
Dim linknow%

其中将Winsock的0号标识是一直作为监听口的,始终监听连接准备,方便接下来的操作.
接下来建立一个菜单(因为我觉得比较好看,当然也可以用command代替)(这个不会的话自行百度)
菜单内有[开启服务器]这个栏目(名称叫server_open)(姑且这么叫吧)
在server_open插入如下代码:
程序代码:
Private Sub server_open_Click()
    If (server_open.Caption = "开启服务器") Then
        report.Clear
        LinkClient.Clear
'这部分可以不用
        report.AddItem "服务器已开启."
        report.AddItem "本机名称:" & ServerLink(0).LocalHostName
        report.AddItem "本机地址:" & ServerLink(0).LocalIP
        report.AddItem "本机端口:" & ServerLink(0).LocalPort
'这部分可以不用
        ServerLink(0).Listen    '0号机始终监听
        Command.Locked = False
        server_open.Caption = "关闭服务器"
    ElseIf (server_open.Caption = "关闭服务器") Then
        Do While (linknow > 0)    '关闭所有客户端
            If (ServerLink(linknow).State = 7) Then
                ServerLink(linknow).SendData "[serverclose]|" & LinkClient.List(linknow)
                DoEvents    '将控制权交给系统,用于Winsock发送数据(必须有)
            End If
            ServerLink(linknow).Close
            Unload ServerLink(linknow)    '卸载控件,释放内存
            linknow = linknow - 1
            LinkClient.RemoveItem (linknow)
        Loop
        ServerLink(0).Close    '关闭监听
        Command.Locked = True
        report.AddItem "服务器已关闭."    '这行也可以不用
        server_open.Caption = "开启服务器"
    End If
End Sub

在ServerLink的ConnectionRequest事件中插入如下代码:
程序代码:
Private Sub ServerLink_ConnectionRequest(Index As Integer, ByVal requestID As Long)
    Dim num%, flag%
    For num = 1 To linknow    '搜寻一个未被占用的连接组
        If (ServerLink(num).State = 0) Then
            ServerLink(num).Accept requestID
            ServerLink(num).SendData "[accept]|" & num
            flag = 1    '标志找到并记录变量为1
            Exit For
        End If
    Next num
    If (num = 100) Then    '如果达到最大链接数,向客户端发送服务器链接达到最大数的消息
        ServerLink(0).Accept requestID
        ServerLink(0).SendData "[linkmax]|9999"
        DoEvents
        ServerLink(0).Close
        ServerLink(0).Listen
    ElseIf (flag = 0) Then    '如果没找到连接组且连接数未达到最大值时则载入一个Winsock控件并建立这个链接
        linknow = linknow + 1
        Load ServerLink(linknow)
        ServerLink(linknow).Accept requestID
        ServerLink(linknow).SendData "[accept]|" & num
        LinkClient.AddItem ""    '加入一个项目方便记录用户昵称
    End If
End Sub

然后在ServerLink的DataArrival事件中加入以下代码:
程序代码:
Private Sub ServerLink_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    Dim data0$, place%, datatype$, data1$, username$
    ServerLink(Index).GetData data0    '获取控件发来的数据
    place = InStr(data0, "|")
    datatype = Left(data0, place - 1)    '获取数据类型
    data1 = Right(data0, Len(data0) - place)    '记录剩余数据
    username = LinkClient.List(Index - 1)
    Select Case (datatype)
        Case "[nickname]"    '接收到[用户昵称]时执行的操作
            LinkClient.List(Index - 1) = data1
            report.AddItem "[system]:" & data1 & "已连接到服务器"
        Case "[logout]"    '接收到[登出]时执行的操作
            ServerLink(Index).Close
            report.AddItem "[system]:" & username & "已断开与服务器的连接"
            LinkClient.List(Index - 1) = ""
        Case "[message]"    '接收到[消息]时执行的操作
            report.AddItem data1
            For num = 1 To linknow    '由服务端向除发送的客户端外的所有已建立链接的客户端发送数据
                If (ServerLink(num).State = 7 And num <> Index) Then
                    ServerLink(num).SendData data0
                    DoEvents
                End If
            Next num
    End Select
End Sub

服务端的设置基本就是这样了
界面设计参考图:

明天我会再发客户端的设计参考(学生党,寝室熄灯了,休息了)

我究竟要什么时候才能变得更强啊...
2018-11-03 23:06
紫苑星苑
Rank: 2
等 级:论坛游民
威 望:2
帖 子:12
专家分:42
注 册:2018-9-2
得分:0 
接4楼,接下来是关于客户端的
客户端这里我是设计了两个窗口,一个是登录窗口,还有一个是会话窗口
登录窗口所需的控件:
1.Label控件3个(不用命名,只是起标识作用的)
2.Text控件3个(分别被命名为:username,hostip,hostport)
控件2个(分别被命名为:cmd_connect,cmd_exit)
在cmd_connect中写下如下代码:
程序代码:
Private Sub cmd_connect_Click()
    If (IsNumeric(hostport.Text) = False) Then
        Call MsgBox("请输入正确的端口号", vbExclamation, "Alert")
        hostport.SetFocus
        Exit Sub
    End If
    username.Locked = True
    cmd_connect.Caption = "登录中"
    cmd_connect.Enabled = False
    Load Client    '载入会话窗口
End Sub

然后退出的方面应该不用我写了吧...
登录窗口界面参考:

会话窗口所需控件:
1.list控件1个(命名为report)
2.text控件1个(命名为message)
4.Winsock控件1个(命名为ClientLink)
5.Timer控件2个(命名为linktest,maxtime)
首先定义两个全局变量:
Public nickname$
Dim shut%

然后在Form中写入如下代码:
程序代码:
Private Sub Form_Load()
    shut = 0    '异常终止标识符
    nickname = ""    '清除原先昵称
    ClientLink.RemoteHost = ClientLogin.hostip.Text
    ClientLink.RemotePort = ClientLogin.hostport.Text
    ClientLink.Connect
End Sub

Private Sub Form_Unload(Cancel As Integer)
    ClientLogin.cmd_connect.Caption = "链接"
    ClientLogin.cmd_connect.Enabled = True
    ClientLogin.username.Locked = False
    If (shut = 1) Then    '如果异常中断标识符生效则不执行接下来的步骤
        Exit Sub
    End If
    Dim ret%
    ret = MsgBox("您确定要断开连接?", 4 + vbQuestion + 256, "Continue?")
    If (ret = 6) Then
        ClientLink.SendData "[logout]|0000"
        DoEvents
        ClientLink.Close
        ClientLogin.Show
        Exit Sub
    End If
    Cancel = 1
End Sub

然后是ClientLink的相关代码:
程序代码:
Private Sub ClientLink_DataArrival(ByVal bytesTotal As Long)
    Dim data0$, place%, datatype$, data1$
    ClientLink.GetData data0
    place = InStr(data0, "|")
    datatype = Left(data0, place - 1)
    data1 = Right(data0, Len(data0) - place)
    Select Case (datatype)
        Case "[linkmax]"    '接收到[服务器已满]时执行的操作
            linktest.Enabled = False
            ClientLink.Close
            shut = 1
            Unload Me
            If (ClientLogin.Visible = False) Then
                ClientLogin.Show
            End If
            Call MsgBox("服务器已满", vbExclamation, "Tip")
        Case "[server]"
            report.AddItem "[Server]:" & data1
        Case "[serverclose]"    '接收到[服务器已关闭]时的操作
            linktest.Enabled = False
            ClientLink.Close
            shut = 1
            Unload Me
            If (ClientLogin.Visible = False) Then
                ClientLogin.Show
            End If
            Call MsgBox("服务器已关闭", vbExclamation, "Tip")
        Case "[accept]"    '接收到[允许连接]时执行的操作
            nickname = ClientLogin.username.Text    '获取用户昵称
            Client.Caption = "客户端[当前用户:" & nickname & "]"
            ClientLink.SendData "[nickname]|" & nickname
            maxtime.Enabled = False    '停止连接超时检测
            report.AddItem "登录成功"
            report.AddItem "本机号码:" & ClientLink.LocalHostName
            report.AddItem "本机IP地址:" & ClientLink.LocalIP
            report.AddItem "本机端口:" & ClientLink.LocalPort
            ClientLogin.username.Text = ""
            ClientLogin.cmd_connect.Enabled = True
            ClientLogin.Hide
            Client.Show
        Case "[message]"
            report.AddItem data1
    End Select
End Sub
Private Sub ClientLink_Error(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)
    maxtime.Enabled = False
    If (Number = 10061) Then
        Call MsgBox("服务器未开启", vbExclamation, "Tip")
    ElseIf (Number = 10065) Then
        Call MsgBox("没有网络连接.", vbExclamation, "Tip")
    Else
        Call MsgBox("抱歉,连接失败." & Chr(10) & "错误编号:" & Number & Chr(10) & "错误描述:" & Description, vbExclamation, "Alert")
    End If
    ClientLink.Close
    shut = 1
    Unload Me
End Sub

然后是超时检测和状态检测
超时检测的Timer的Interval设置为5000
程序代码:
Private Sub maxtime_Timer()
    maxtime.Enabled = False
    shut = 1
    Unload Me
    Call MsgBox("链接超时", vbExclamation, "Alert")
End Sub

状态检测的Timer的Interval设置为1000
程序代码:
Private Sub linktest_Timer()
    If (ClientLink.State = 8) Then
        linktest.Enabled = False
        ClientLink.Close
        ClientLogin.Show
        shut = 1
        Unload Me
        Call MsgBox("与服务器断开连接", vbExclamation, "Alert")
        Exit Sub
    End If
End Sub

最后是发送消息的这部分
程序代码:
Private Sub message_KeyPress(KeyAscii As Integer)
    If (KeyAscii <> 13) Then
        Exit Sub
    ElseIf (message.Text = "") Then
        KeyAscii = 0
        Exit Sub
    End If
    If (ClientLink.State = 7) Then
        report.AddItem "[You]:" & MessageBox.Text
        ClientLink.SendData "[message]|[" & nickname & "]:" & MessageBox.Text    '发送数据(联系服务端的数据处理)
    End If
    message.Text = ""
    KeyAscii = 0    '取消回车所造成的'登'的声音
End Sub

对了,还有服务端的发送消息部分
程序代码:
Private Sub Command_KeyPress(KeyAscii As Integer)
    If (KeyAscii <> 13) Then
        Exit Sub
    End If
    Dim cmd$(), data_send$, num%
    data_send = "[server]|" & Command.Text
    For num = 1 To linknow
        If (ServerLink(num).State = 7) Then
            ServerLink(num).SendData data_send
            DoEvents
        End If
    Next num
    report.AddItem "[Server]:" & Command.Text
    Command.Text = ""
    KeyAscii = 0
End Sub

差不多就是这样了...
参考的客户端界面图:


PS:
因为原程序已经被我魔改的加入了一堆乱七八糟的东西,所以以上内容是我删删改改的结果,有概率存在bug,然后也因为这个原因我就不贴原程序了...

[此贴子已经被作者于2018-11-4 19:04编辑过]


我究竟要什么时候才能变得更强啊...
2018-11-04 10:37
leziyi
Rank: 1
等 级:新手上路
帖 子:52
专家分:0
注 册:2016-10-30
得分:0 
发现BUG:变量未定义
Private Sub Form_Unload(Cancel As Integer)
    ClientLogin.cmd_connect.Caption = "链接"
    ClientLogin.cmd_connect.Enabled = True
    ClientLogin.username.Locked = False
    If (shut = 1) Then    '如果异常中断标识符生效则不执行接下来的步骤
        Exit Sub
    End If
    Dim ret%
    ret = MsgBox("您确定要断开连接?", 4 + vbQuestion + 256, "Continue?")
    If (ret = 6) Then
        ClientLink.SendData "[logout]|" & serverid.Caption
        DoEvents
        ClientLink.Close
        ClientLogin.Show
        Exit Sub
    End If
    Cancel = 1
End Sub
2018-11-04 17:59
leziyi
Rank: 1
等 级:新手上路
帖 子:52
专家分:0
注 册:2016-10-30
得分:0 
顺便帮忙看一下这段代码:
Private Sub Timer1_Timer()

   If ListView1.ListItems(0).SubItems(0) = "" Then----------------------------------------此行出错
   
      Exit Sub
      
   End If

   Select Case Winsock2(ListView1.SelectedItem.Index).State
   
          Case 0
         
               Label4.Caption = "工作状态:" & "未连接"
               
          Case 2
         
               Label4.Caption = "工作状态:" & "正在监听......"
               
          Case 4
         
               Label4.Caption = "工作状态:" & "正在解析域名......"
               
          Case 6
         
               Label4.Caption = "工作状态:" & "正在连接......"
               
          Case 7
         
               Label4.Caption = "工作状态:" & "已连接"
               
          Case 8
         
               Label4.Caption = "工作状态:" & "对方正在关闭连接......"
               
          Case 9
         
               Label4.Caption = "工作状态:" & "连接错误"
               
   End Select

End Sub
2018-11-04 18:50
紫苑星苑
Rank: 2
等 级:论坛游民
威 望:2
帖 子:12
专家分:42
注 册:2018-9-2
得分:0 
回复 6楼 leziyi
我确认了一下,那个serverid控件可以不用,忘了删了
然后关于7楼,因为我没用过ListView控件控件,所以不是很明白你那是什么意思

我究竟要什么时候才能变得更强啊...
2018-11-04 19:01
leziyi
Rank: 1
等 级:新手上路
帖 子:52
专家分:0
注 册:2016-10-30
得分:0 
2018-11-04 19:49
leziyi
Rank: 1
等 级:新手上路
帖 子:52
专家分:0
注 册:2016-10-30
得分:0 
就是用户列表框架里面那个
2018-11-04 19:50



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-490731-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.100496 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved