VB6 winsock服务器和多个arduino客户端问题

Posted

技术标签:

【中文标题】VB6 winsock服务器和多个arduino客户端问题【英文标题】:VB6 winsock server and multiple arduino clients issue 【发布时间】:2017-08-25 14:30:12 【问题描述】:

现在我正在开发一个工具,它允许我使用 VB6 和带有以太网屏蔽的 arduino UNO 测量网络连接之间的延迟。 现在我面临一些服务器代码(VB6 程序)的问题。 我有 2 个带有两个不同端口的 winsock,它们都在监听 arduino 客户端进行连接。现在,如果我只有一个活动连接,一切都不会出错,一切正常,但是一旦第二个客户端连接,整个服务器就会开始发疯。突然它报告说第一个连接的客户端失去了连接,所以简而言之,服务器只是不希望一次连接 2 个客户端,但我确实需要它:/ 出了什么问题?

我将快速解释通过 winsock 向服务器发送或从服务器发送的 sertain 命令。

"SERVER_SLEEP" Is a command that the server sends to all clients that will tell them to enter a power saving mode. "SERVER_REQUESTS_DATA" Is a command that the server sends to a specific client and forces the client to send information like Device name and firmware version. "RESPOND_MESSAGE" Is a command that the server sends to all clients and the client is forced to respond to see if we still have an connection. "DEVICE_NAME=" Is a command that the client sends to the server when it just connects, It is required before we show that we have an connection by putting it into the listbox. (after the = comes the device name) "DEVICE_NAME_REP=" Is a command that the client sends to the server when the server requests information about the client, the reason i have 2 of them is because i couldn't reuse the previous one since then it would become way to complicated. (after the = comes the device name) "DEVICE_FIRMWARE=" Is a command that the client sends to the server when the server requests information about the client. (after the = comes the device firmware version) "DEVICE_OK=" Is a command that the client sends to the server when the server requests an answer to check if we still have an connection. (after the = comes the device name) "DEVICE_REBOOTING" Is a command that the client sends to the server when it goes out of sleep mode (it goes out of that mode when the server comes back online again after it was closed) After the client send that message it immediately closes the connection again and the device is forced to reboot to make sure nothing goes wrong.

我的代码:

Dim DeviceIP1 As String
Dim DeviceIP2 As String
Dim UpdateListStatus As Integer

Private Sub Command1_Click()
MsgBox Socket1.State
MsgBox Socket2.State
End Sub

Private Sub Command3_Click()
If Dir(App.Path & "\TH.exe") <> "" Then 'Traceroute Helper application i wrote before, Works 100% and is not relevant for the issue i am facing
Shell App.Path & "\TH.exe " & DeviceIP, vbNormalFocus
Else
MsgBox "Missing file!" & vbNewLine & "File TH.exe is required for the requested operation!", vbCritical + vbSystemModal, "Missing file"
End If
End Sub

Private Sub Form_Load()
Socket1.Listen
Socket2.Listen
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
Dim msg As VbMsgBoxResult
msg = MsgBox("Are you sure you want to exit?" & vbNewLine & "All the clients will be put into sleep mode.", vbYesNo + vbQuestion + vbSystemModal, "Quit")
If msg = vbYes Then
  Form3.Show
  Cancel = True
  Form1.Visible = False
Else
  Cancel = True
End If
End Sub

Private Sub List1_Click()
On Error GoTo errhandler
Dim ClientFound As Boolean
DeviceIP = Mid(List1.Text, InStr(List1.Text, "-") + 1)
DeviceIP = LTrim(DeviceIP)
DeviceIPLabel.Caption = "Device IP: " & DeviceIP
Form2.Show
    If Socket1.RemoteHostIP = DeviceIP Then
    Socket1.SendData ("SERVER_REQUESTS_DATA")
    ElseIf Socket2.RemoteHostIP = DeviceIP Then
    Socket2.SendData ("SERVER_REQUESTS_DATA")
    End If
Exit Sub
errhandler:
If Err.Number = 40006 Then
MsgBox "Socket error!" & vbNewLine & "The requested device might be offline.", vbCritical + vbSystemModal, "Socket error"
Unload Form2
End If
End Sub

Private Sub UpdateList_Timer()
On Error Resume Next
If List1.ListCount > 0 Then
If UpdateListStatus = 0 Then
TempList.Clear

Socket1.SendData ("RESPOND_MESSAGE")
Socket2.SendData ("RESPOND_MESSAGE")

UpdateListStatus = 1
UpdateList.Interval = 5000
ElseIf UpdateListStatus = 1 Then
List1.Clear
For x = 0 To TempList.ListCount
List1.AddItem (TempList.List(x))
Next x

For X2 = 0 To List1.ListCount
If List1.List(X2) = "" Then 'Check if we have any items that are nothing
List1.RemoveItem (X2)
End If
Next X2

Label1.Caption = "Connected clients: " & List1.ListCount
UpdateListStatus = 0
UpdateList.Interval = 10000
End If
End If
End Sub

Private Sub Socket1_DataArrival(ByVal bytesTotal As Long)
On Error Resume Next
Dim TempString As String
Dim TempString2 As String
Dim position As Integer

Socket1.GetData TempString, vbString
    position = InStr(1, TempString, "DEVICE_NAME=")
    If position > 0 Then 'It is a device name command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       List1.AddItem (TempString2 + " - " + Socket1.RemoteHostIP)
       Label1.Caption = "Connected clients: " & List1.ListCount
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_NAME_REP=")
    If position > 0 Then 'It is a device name command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       DeviceNameLabel.Caption = "Device name: " & TempString2
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_FIRMWARE=")
    If position > 0 Then 'It is a device firmware command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       DeviceFirmwareLabel.Caption = "Firmware version: " & TempString2
       Unload Form2 'Since this is the last piece we will be receiving we can close this window
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_OK=")
    If position > 0 Then 'It is a device respond command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       TempList.AddItem (TempString2 + " - " + Socket1.RemoteHostIP)
       Label1.Caption = "Connected clients: " & List1.ListCount
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_REBOOTING")
    If position > 0 Then 'It is a device respond command from a client
       Socket1.Close
       TempString2 = ""
    End If
Text1.Text = Text1.Text & TempString & vbNewLine
TempString = ""
position = 0
TempString2 = ""
End Sub

Private Sub Socket2_DataArrival(ByVal bytesTotal As Long)
On Error Resume Next
Dim TempString As String
Dim TempString2 As String
Dim position As Integer

Socket2.GetData TempString, vbString
    position = InStr(1, TempString, "DEVICE_NAME=")
    If position > 0 Then 'It is a device name command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       List1.AddItem (TempString2 + " - " + Socket2.RemoteHostIP)
       Label1.Caption = "Connected clients: " & List1.ListCount
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_NAME_REP=")
    If position > 0 Then 'It is a device name command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       DeviceNameLabel.Caption = "Device name: " & TempString2
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_FIRMWARE=")
    If position > 0 Then 'It is a device firmware command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       DeviceFirmwareLabel.Caption = "Firmware version: " & TempString2
       Unload Form2 'Since this is the last piece we will be receiving we can close this window
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_OK=")
    If position > 0 Then 'It is a device respond command from a client
       TempString2 = Mid(TempString, InStr(TempString, "=") + 1)
       TempList.AddItem (TempString2 + " - " + Socket2.RemoteHostIP)
       Label1.Caption = "Connected clients: " & List1.ListCount
       TempString2 = ""
    End If
    position = 0
    position = InStr(1, TempString, "DEVICE_REBOOTING")
    If position > 0 Then 'It is a device respond command from a client
       Socket2.Close
       TempString2 = ""
    End If
Text1.Text = Text1.Text & TempString & vbNewLine
TempString = ""
position = 0
TempString2 = ""
End Sub


Private Sub Socket1_ConnectionRequest(ByVal requestID As Long)
If Socket1.State <> sckClosed Then
    Socket1.Close
    ' Accept the request with the requestID
    ' parameter.
    Socket1.Accept requestID
End If
End Sub

Private Sub Socket2_ConnectionRequest(ByVal requestID As Long)
If Socket2.State <> sckClosed Then
    Socket2.Close
    Socket2.Accept requestID 'Allow the connection
End If
End Sub

`

【问题讨论】:

你是如何连接的? TCP ?如果是这样,您是否使用不同的端口?请发布一些代码。 抱歉,不小心按回车键,所以没有可用的代码:/ 哦,我使用 TCP,socket1 使用端口 2444,socket2 使用端口 2445 【参考方案1】:

那里有很多东西需要挖掘(您可能想尝试创建问题的MCVE 只是为了让您自己的调试更容易),但乍一看那些ConnectionRequest 事件处理程序对我来说似乎是可疑的。 Winsock Control ConnectionRequest Event documentation 表示“使用 Accept 方法(在新控件实例上)接受传入连接。”您正在尝试以某种方式使用相同的控件实例,这可能是一种方法,但不是标准方法。

如果内存有用(自从我处理这个问题以来一直存在),你想创建一个 Winsock Controls 的Control Array,并在运行时创建一个新实例load 来处理每个新连接(并卸载它)连接完成时)。 “监听”控件和“处理当前连接”控件需要是不同的实例。这样,每个实例都会使用自己的状态处理自己的连接,并且侦听器可用于处理任何新的传入连接。

【讨论】:

我将制作一个 MCVE 版本,但我看不出 ConnectionRequest 事件有什么问题。除非我不知道你知道的事情。哦,在此之前我使用了一个 winsock 数组,但它给了我更多的问题,比如如果我需要向某个客户端发送消息,我需要找到连接到该特定客户端的 winsock。 我刚刚制作了一个只有基础的 MCVE 版本,但它仍然失去连接:/ 所以保持连接有问题。我什至可以看到完整的消息,当我发送强制响应消息时,我只收到来自 1 个客户端的响应,而失去连接的客户端始终是第一个连接的客户端,所以我认为第二个 winsock 正在干扰第一个温索克。不知道为什么,但它发生了 @SanderB.嗯,是的,您的 ConnectionReceived 事件表明要做的第一件事是关闭其现有连接,这就是它的作用。您将如何处理多个连接而不需要跟踪哪个连接正在由哪个控件处理?【参考方案2】:

好的,所以我能够为多客户端服务器找到一个非常好的示例代码 而且我还发现我创建的超时延迟太短了,所以这就是它从列表中消失的原因。有时需要 10 秒才能收到响应,并且超时设置为 MAX 仅 5 秒。 但仍然感谢您尝试帮助我:)

示例代码链接:LINK

【讨论】:

以上是关于VB6 winsock服务器和多个arduino客户端问题的主要内容,如果未能解决你的问题,请参考以下文章

vb6 - 将消息发送到winsock服务器聊天

VB6 中的默认 WinSock 协议

VB6 Winsock 能够发送非常大的有效载荷

使用 vb6 winsock 发送 python 字符串

我在 vb6(winsock) 中创建的客户端/服务器程序不能在 WAN 上运行,但可以在 LAN 上完美运行 为啥?

请问:在VB6.0中使用winsock控件,作为服务器要设置本地IP地址吗?