socket编程 多个服务端如何收发数据?

hbhuo2008 2020-03-29 09:50:04
最近在开发一个程序,做客户端的,服务端是购买的设备,看不到源码,采用tcp协议,socket连接。

这个程序目的是与n个服务端建立socket连接然后逐个收发数据,处理数据,保存数据。

现在遇到问题,一对一好处理,n个连接如何处理socket?用数组存储?如何收发数据?

求大神帮忙指点!

...全文
990 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
小灯塔 2020-04-20
  • 打赏
  • 举报
回复
用vb做多线程有点用其短,我曾经把socket做成组件,用创建对象的方法处理
hbhuo2008 2020-04-13
  • 打赏
  • 举报
回复
看看我这对接收数据进行处理的代码是不是也有问题。
 'apc>atsMeasure获取电压、功率值
        'E000:   Success()
        'Source A Freq:              50 Hz
        'Source A Voltage:           218 V
        'Source B Freq:              50 Hz
        'Source B Voltage:           219 V
        'Total Output Power:         0.31 kVA
        'Source A 24V Power Supply:  24 V
        'Source B 24V Power Supply:  24 V
        'Source A Boost Voltage:     48 V
        'Source B Boost Voltage:     48 V
        '3.3V Power Supply:          3.3 V
        '1.0V Power Supply:          1.0 V
        Dim ATS_T As Boolean = TextStr.Contains("Total Output Power:")
        If ATS_T = True Then
            Dim temp1, temp2, temp3, temp4, temp5 As String
            Dim h1 As Integer
            Dim TOP(), tp1(), tp2() As String
            TOP = Split(TextStr, vbCrLf) '每-行插入数组
            If UBound(TOP) < 12 Then
                Exit Sub
            End If
            For h1 = 0 To UBound(TOP) - 4
                temp1 = InStr(1, TOP(h1), "Source A Freq:", 0)
                If temp1 > 0 Then
               
                    tp1 = Split(TOP(h1).Replace(" ", ""), ":") '去掉空格
                
                    tp2 = Split(tp1(1), "Hz")
                
                    ATS1_FA = tp2(0) '频率
                End If
                temp2 = InStr(1, TOP(h1 + 1), "Source A Voltage:", 0)  
                If temp2 > 0 Then
                    tp1 = Split(TOP(h1 + 1).Replace(" ", ""), ":")
                    tp2 = Split(tp1(1), "V")
                    ATS1_VA = tp2(0) 'a电压
                End If
                temp3 = InStr(1, TOP(h1 + 2), "Source B Freq:", 0)    
                If temp3 > 0 Then
                    tp1 = Split(TOP(h1 + 2).Replace(" ", ""), ":") '去掉空格
                    tp2 = Split(tp1(1), "Hz")
                    ATS1_FB = tp2(0) '频率
                End If
                temp4 = InStr(1, TOP(h1 + 3), "Source B Voltage:", 0)   
                If temp4 > 0 Then
                    tp1 = Split(TOP(h1 + 3).Replace(" ", ""), ":") '去掉空格
                    tp2 = Split(tp1(1), "V")
                    ATS1_VB = tp2(0) 'b电压
                End If
                temp5 = InStr(1, TOP(h1 + 4), "Total Output Power:", 0)  
                If temp5 > 0 Then
                    tp1 = Split(TOP(h1 + 4).Replace(" ", ""), ":") '去掉空格
                    tp2 = Split(tp1(1), "kVA")
                    ATS1_P = tp2(0) '总功率
                End If
            Next
            Dim u1 As Integer
            '修改列表值
            For u1 = 0 To ListView1.Items.Count - 1
                If ListView1.Items(u1).SubItems(2).Text.Trim = IPPORT Then '连接参数
                    ListView1.Items(u1).SubItems(3).Text = ATS1_FA & "Hz/" & ATS1_VA & "V" 'A路电压
                    ListView1.Items(u1).SubItems(4).Text = ATS1_FB & "Hz/" & ATS1_VB & "V" 'B路电压
                    ListView1.Items(u1).SubItems(5).Text = ATS1_P & "kVA" '总功率
                    If IsNumeric(ATS1_P) = True And IsNumeric(ATS1_VA) = True Then
                        ListView1.Items(u1).SubItems(6).Text = Int(ATS1_P * 1000 / Int(ATS1_VA) * 100) / 100 & "A" '电流
                    Else
                        ListView1.Items(u1).SubItems(6).Text = " A"
                    End If
                    ListView1.Items(u1).SubItems(13).Text = TimeOfDay() '更新时间
                    ListView1.Items(u1).SubItems(15).Text = "atsMeasure"
                    TxtBox_S1.Text = ATS1_P & "* 1000 /" & ATS1_VA & " * 100) / 100 A" & vbCrLf & TxtBox_S1.Text
                End If

            Next
            '发送查询
            dic(IPPORT).Send(Encoding.Default.GetBytes("atsStatus"))
            '发送回车键
            ent(dic(IPPORT))
        End If
 'apc>atsStatus 获取状态
        'E000: Success
        'Communication Status:       OK
        'Selected Source:            Source A
        'Preferred Source:           Source A
        'Switch Status:              OK
        'Front Panel:                Unlocked
        'Source A:                   Selected
        'Source B:                   OK
        'Phase Synchronization:      Out of sync
        'Source A 24V Power Supply:  OK
        'Source B 24V Power Supply:  OK
        'Source A Boost Voltage:     OK
        'Source B Boost Voltage:     OK
        '3.3V Power Supply:          OK
        '1.0V Power Supply:          OK
        Dim ATS_S As Boolean = TextStr.Contains("Selected Source:")
        If ATS_S = True Then
            Dim temp1, temp2, temp3, temp4, temp5 As String
            Dim h As Integer
            Dim SS(), tp1() As String
            SS = Split(TextStr, vbCrLf) '每-行插入数组
            If UBound(SS) < 13 Then
                Exit Sub
            End If
            For h = 0 To UBound(SS) - 5
                temp1 = InStr(1, SS(h), "Selected Source:", 0)
                If temp1 > 0 Then
                    'TextBox1.Text = TextBox1.Text & vbCrLf & SS(h) '获取整行
                    tp1 = Split(SS(h), ":")
                    ATS1_Selected = LTrim(tp1(1)) '在线选路
                End If
                temp2 = InStr(1, SS(h + 1), "Preferred Source", 0)
                If temp2 > 0 Then
                    tp1 = Split(SS(h + 1), ":")
                    ATS1_Preferred = LTrim(tp1(1)) '优先选路
                End If
                temp3 = InStr(1, SS(h + 2), "Switch Status", 0)
                If temp3 > 0 Then
                    tp1 = Split(SS(h + 2).Replace(" ", ""), ":")
                    ATS1_Switch = tp1(1) '开关状态
                End If
                'temp1 = InStr(1, SS(h), "Communication Status:", 0)
                'If temp1 > 0 Then
                '    tp1 = Split(SS(h).Replace(" ", ""), ":")
                '    ATS1_C = tp1(1) '通信状态
                'End If
                temp4 = InStr(1, SS(h + 4), "Source A:", 0)
                If temp4 > 0 Then
                    tp1 = Split(SS(h + 4).Replace(" ", ""), ":")
                    tempA = tp1(1) 'A路状态
                End If
                temp5 = InStr(1, SS(h + 5), "Source B:", 0)
                If temp5 > 0 Then
                    tp1 = Split(SS(h + 5).Replace(" ", ""), ":")
                    tempB = tp1(1) 'B路状态
                End If
            Next
            '修改列表值
            Dim u2 As Integer
            For u2 = 0 To ListView1.Items.Count - 1
                If ListView1.Items(u2).SubItems(2).Text.Trim = IPPORT Then '连接参数
                    ListView1.Items(u2).SubItems(7).Text = ATS1_Preferred '优先线路
                    ListView1.Items(u2).SubItems(8).Text = ATS1_Selected '当前选择
                    ListView1.Items(u2).SubItems(9).Text = tempB '备路状态
                    ListView1.Items(u2).SubItems(10).Text = ATS1_Switch '开关状态
                    ListView1.Items(u2).SubItems(13).Text = TimeOfDay() '更新时间
                    ListView1.Items(u2).SubItems(15).Text = "atsStatus"
                    '判断是否切换
                    If ATS1_Selected <> ATS1_Preferred Then
                        ListView1.Items(u2).BackColor = Color.Red
                        '写日志
                        'logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "ERRLOG.txt"
                        'writelogdata(logfilepath, Now & " " & IPPORT & "设备当前选择异常:" & ATS1_Preferred & "。")
                        INFO_SSLable.Text = Now & " " & IPPORT & "设备当前选择:" & ATS1_Preferred & "。"
                        TextBox1.Text = Now & " " & IPPORT & "设备当前选择:" & ATS1_Preferred & "。" & vbCrLf & TextBox1.Text
                    Else
                        ListView1.Items(u2).BackColor = btncr
                    End If
                    '判断备路状态
                    If tempB <> "OK" Then
                        ListView1.Items(u2).BackColor = Color.Red
                        '写日志
                        'logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "ERRLOG.txt"
                        'writelogdata(logfilepath, Now & " " & IPPORT & "设备备路状态异常:" & tempB & "。")
                        INFO_SSLable.Text = Now & " " & IPPORT & "设备备路状态异常:" & tempB & "。"
                        TextBox1.Text = Now & " " & IPPORT & "设备备路状态异常:" & tempB & "。" & vbCrLf & TextBox1.Text
                    Else
                        ListView1.Items(u2).BackColor = btncr
                    End If
                    '判断开关状态
                    If ATS1_Switch <> "OK" Then
                        ListView1.Items(u2).BackColor = Color.Red
                        ''写日志
                        'logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "ERRLOG.txt"
                        'writelogdata(logfilepath, Now & " " & IPPORT & "设备开关状态异常:" & ATS1_Switch & "。")
                        INFO_SSLable.Text = Now & " " & IPPORT & "设备开关状态异常:" & ATS1_Switch & "。"
                        TextBox1.Text = Now & " " & IPPORT & "设备开关状态异常:" & ATS1_Switch & "。" & vbCrLf & TextBox1.Text
                    Else
                        ListView1.Items(u2).BackColor = btncr
                    End If
                End If
            Next
        End If
hbhuo2008 2020-04-13
  • 打赏
  • 举报
回复
上面是部分代码,其他具体数据处理没有贴出来。 现有几个问题 1、socket的发送和接收用Encoding.Default.GetString()方式 有些字符串数据接收分好几段才能接收完整。比如name,一次只收到一个字母,不好处理数据。 2、在Timer1_Tick写了60秒轮询向ListView1里可连接的socket发送查询码, 首次可以接收数据,后面向所有socket发送查询就只能接收一两个socket的数据。 3、接收数据判断处理后更改ListView1的项数据也有问题,更改行也有错误。 所有项的修改和发送码都是以连接参数(IP和端口)为判断字段。
hbhuo2008 2020-04-13
  • 打赏
  • 举报
回复
各路大神,看看我写的代码,用字典方式存储socket连接。 程序启动界面: 运行界面
 '连接ATS设备,连接函数
    Private Sub con_ats_ipport(ByVal Str As String)

        Dim i As Integer
        Dim atsname, con_ipport, ipport() As String
        For i = 0 To ListView1.Items.Count - 1
            If ListView1.Items(i).SubItems(12).Text.Trim = Str Then
                Try
                    atsname = ListView1.Items(i).SubItems(1).Text 'ATS名称
                    con_ipport = ListView1.Items(i).SubItems(2).Text '连接参数
                    ipport = Split(con_ipport, ":")
                    '现在尝试连接atsname服务端,ipport(0)为IP,ipport(1)为端口

                    TextBox1.Text = Now & " 现在连接" & atsname & "。" & vbCrLf & TextBox1.Text

                    Dim siteResponds As Boolean = False
                    siteResponds = My.Computer.Network.Ping(ipport(0)) 'ping IP地址查看是否可用
                    If siteResponds = False Then
                        ListView1.Items(i).SubItems(12).Text = "连接失败"

                        TextBox1.Text = Now & " " & atsname & "的IP地址不可用。" & vbCrLf & TextBox1.Text
                        '写日志
                        'logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "LOG.txt"
                        'writelogdata(logfilepath, Now & " " & atsname & "的IP地址不可用。")
                    Else
                        Dim localEndPoint1 As New IPEndPoint(IPAddress.Parse(ipport(0)), ipport(1))
                        ListenSocket = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                        ListenSocket.Connect(localEndPoint1)
                        If ListenSocket.Connected = True Then
                            dic.Add(ListenSocket.RemoteEndPoint.ToString, ListenSocket)
                            '禁用线程检测
                            Control.CheckForIllegalCrossThreadCalls = False
                            '创建一个线程用于接收数据
                            LinkThread = New Thread(AddressOf ReciveData)
                            '设置为后台进程
                            LinkThread.IsBackground = True
                            LinkThread.Start(ListenSocket)

                            ComboBox_Socket.Items.Add(ListenSocket.RemoteEndPoint.ToString) '把连接到的服务端IP和端口存到下拉框里

                            ListView1.Items(i).SubItems(12).Text = "已连接"
                            ConLis = True
                            TextBox1.Text = Now & " " & atsname & "连接成功。" & vbCrLf & TextBox1.Text
                            '写日志
                            logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "LOG.txt"
                            writelogdata(logfilepath, Now & " " & atsname & "端口连接成功。")
                        Else
                            ListView1.Items(i).SubItems(12).Text = "连接失败"
                            TextBox1.Text = Now & " " & atsname & "端口连接失败。" & vbCrLf & TextBox1.Text
                            '写日志
                            logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "LOG.txt"
                            writelogdata(logfilepath, Now & " " & atsname & "端口连接失败。")
                        End If
                        Thread.Sleep(200)
                    End If

                Catch ex As Exception
                    logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "ERRLOG.txt"
                    writelogdata(logfilepath, Now & " " & Str & "错误:" & ex.Message)
                    TextBox1.Text = Now & " " & Str & vbCrLf & TextBox1.Text
                End Try
            End If
        Next
    End Sub
 '侦听线程,接收数据
    Private Sub ReciveData(ByVal s As Object)

        While True
            Dim Socketcon As Socket
            Socketcon = s
            If ConLis = True Then
                Dim bytes(4096) As Byte
                Dim p() As String
                Dim NumGet As Integer = Socketcon.Receive(bytes)
                If Encoding.Default.GetString(bytes, 0, NumGet).Length > 0 Then
                    p = Split(Socketcon.RemoteEndPoint.ToString, ":")
                    If p(1) = ATSGroup(0, 1) Then‘端口为2000
                        '显示服务端发来的消息
                        Receive_TXT11.Text = Now & vbCrLf & Socketcon.RemoteEndPoint.ToString & vbCrLf & Encoding.Default.GetString(bytes, 0, NumGet)

                    Else
                        '显示服务端发来的消息,端口为3000
                        Receive_TXT12.Text = Now & vbCrLf & Socketcon.RemoteEndPoint.ToString & vbCrLf & Encoding.Default.GetString(bytes, 0, NumGet)
                    End If
                    'sqlstr = "INSERT INTO ats_history(ipport,re_time,re_data)VALUES('" & Socketcon.RemoteEndPoint.ToString & "', '" & Now & "', '" & Encoding.Default.GetString(bytes, 0, NumGet) & "')"
                    'If InsertRow(sqlstr) Then
                    '    'MessageBox.Show(LocalIP, "ok", MessageBoxButtons.OK)
                    'End If

                End If
            End If
        End While
    End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        ToolStripStatusLabel2.Text = Now '状态栏显示系统时间

        '0点刷新清空日志
        If TimeOfDay = "0:00:01" Then
            TextBox1.Text = Now & " "
        End If

        '初始连接ATS采集盒
        If ConLis = False Then
            con_ats_ipport("端口启用")
        End If

        '有连接失败,重新连接,5秒检查一次
        If Conlis_F_time <> 0 Then
            Conlis_F_time = Conlis_F_time - 1
        Else
            con_ats_ipport("连接失败")
        End If

    End Sub    
      
                       
收到的数据进行处理
  '处理接收到的数据
    Private Sub Receive_TXT11_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles Receive_TXT11.TextChanged
        If Receive_TXT11.Text.Trim = "" Then
            Exit Sub
        End If
        TextBox2.Text = Receive_TXT11.Lines(1).Trim

        Dim line As String = Receive_TXT11.Text.Trim
        Dim ATS_u As Boolean = line.Contains("User Name")
        Dim ATS_p As Boolean = line.Contains("Password")

        Dim ATS1_OK As Boolean = line.Contains("Super User") '登录成功'型号AP4423
        Dim ATS2_OK As Boolean = line.Contains("Administrator") '型号AP7723
        Dim ATS1_OKed As Boolean = line.Contains("apc>") '已登录过
        Dim ATS2_OKed As Boolean = line.Contains("--- Control Console ---") '型号AP7723

        Dim ATS_by As Boolean = line.Contains("Bye.") '退出 ,则重新登录
        Dim ATS2_by As Boolean = line.Contains("Logging out") '型号AP7723

        Dim ESC_b As Boolean = line.Contains("<ESC>-")
        Dim ATS2_h As Boolean = line.Contains("----")

        Dim ATS2_DM As Boolean = line.Contains("-- Device Manager --")
        Dim ATS_SNMP As Boolean = line.Contains("-- SNMP --")

        ATS1_IPPORT = Receive_TXT11.Lines(1).Trim   '获取选定的客户端IP地址和端口
       
        'Try
        '发送登录用户和密码apc
        If ATS_u = True Or ATS_p = True Then
            dic(ATS1_IPPORT).Send(Encoding.Default.GetBytes("apc"))
            '发送回车键
            ent(dic(ATS1_IPPORT))
        End If

        '登录成功
        If ATS1_OK = True Or ATS2_OK = True Or ATS1_OKed Or ATS2_OKed Then
            Dim g As Integer
            For g = 0 To ListView1.Items.Count - 1
                If ListView1.Items(g).SubItems(2).Text.Trim = ATS1_IPPORT And ListView1.Items(g).SubItems(12).Text = "已连接" Then
                    ListView1.Items(g).SubItems(12).Text = "登录成功"

                    TextBox1.Text = Now & " " & ListView1.Items(g).SubItems(1).Text.Trim & "设备登录成功,查询设备信息。" & vbCrLf & TextBox1.Text
                    '写日志
                    'logfilepath = logdirpath1 + "\" & Now.Year & "-" & Now.Month & "-" & Now.Day & "LOG.txt"
                    'writelogdata(logfilepath, Now & " " & ListView1.Items(j).SubItems(1).Text.Trim & "设备登录成功。")
                    ''型号AP4423,AP7723
                    If ListView1.Items(g).SubItems(14).Text.Trim = "AP4423" Then
                        dic(ATS1_IPPORT).Send(Encoding.Default.GetBytes("aboutATS"))
                        '发送回车键
                        ent(dic(ATS1_IPPORT))
                        ListView1.Items(g).SubItems(15).Text = "aboutATS"
                        Thread.Sleep(100)
                    ElseIf ListView1.Items(g).SubItems(14).Text.Trim = "AP7723" Then
                        dic(ATS1_IPPORT).Send(Encoding.Default.GetBytes("1"))
                        '发送回车键
                        ent(dic(ATS1_IPPORT))
                        Thread.Sleep(100)
                        dic(ATS1_IPPORT).Send(Encoding.Default.GetBytes("8"))
                        '发送回车键
                        ent(dic(ATS1_IPPORT))
                        ListView1.Items(g).SubItems(15).Text = "8"
                    End If
                End If
                'Thread.Sleep(100)
            Next
            LoginLis = True
        End If

       。。。。。。

贫下码农e 2020-04-10
  • 打赏
  • 举报
回复
连接多个服务器要用多线程,连多少台服务器就开多少个线程,把你现在用的一对一的连接和处理数据的方式放在每一个线程上处理,不用担心socket的处理问题,因为线程中的socket都是独立存在的相互不会影响,不过要注意一点的是,原来用一对一用到的在公共变量public声明的socket或是处理数据的数组都要修改为局部变量,如在过程中的用dim分配。
raynors 2020-04-08
  • 打赏
  • 举报
回复
三种解决办法 1\短连接, 既然一个连接没问题,我单线程 开一个连接 获取数据后关闭连接,找下一个IP再连; 这种属于串式通讯,效率不高. 2\多线程长连接,跟上面那个没什么差别.只是你有几个服务器就要开几个线程 ,这个属于简单粗暴的搞法. 这种属于并发通信,效率高,但是资源消耗较大. 3\线程池短连接,可以达到高并发,结合1,2的搞法,控制线程数量能达到相当好的效率.
by_封爱 2020-04-08
  • 打赏
  • 举报
回复
谁连你的 都是有实例的......
良朋 2020-03-31
  • 打赏
  • 举报
回复
多个服务器你就建立多个连接呗,
  • 打赏
  • 举报
回复
客户端连接服务端进行通信,其实只需要两个方法就行。 第一个方法,根据服务器IP和端口创建通信,可以写一个通用的方法,参数为服务器Ip和端口,创建连接。连接生成后可以用字典的方式存储连接。key:value,key为服务器ip和端口,value为创建的clientsocket。 创建好连接后开启一个线程调用第二个方法接收数据。 第二个方法,传入参数为clientsocket,方法目的是循环接收服务器传来的数据,传来的数据怎么处理,就在这里完成。 如果客户端要向服务端发数据,遍历字典根据服务器ip和端口找到对应的socket,socket.sent就行了。 另外还要注意一下连接是否断开,如果有断开的就从字典里删除对应的key:value
wanghui0380 2020-03-30
  • 打赏
  • 举报
回复
俺们回答不了,因为找个不涉及技术 比如 @服务器a “请告诉我现在温度多少” 当前温度指令封包 res= await 服务器a.收到消息(p=>p.指令==当前温度) 找个其实和技术没有关系,既然你连了N个服务器,你想@谁就@谁
qq_42179425 2020-03-30
  • 打赏
  • 举报
回复
几点吧 异步处理 Session机制 主要的网上找找tcp异步通信,会给你答案

16,721

社区成员

发帖
与我相关
我的任务
社区描述
VB技术相关讨论,主要为经典vb,即VB6.0
社区管理员
  • VB.NET
  • 水哥阿乐
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧