0

I am writing some software for some barcode scanners running Windows CE 5.

The software needs to communicate with a server and obtain data. It connects to some software running on a separate computer using a TcpClient.

When it sends data across to the server software, the server software sends a message back saying "Received ## Bytes - " and the command that was sent, so I can clarify that the command has been received correctly (this is because I was having a problem where the string was being "mixed up")

When the barcode scanner receives a response, I want it to then wait for another response with the results of the command.

The problem I'm having, is that the when the TcpClient receives data it calls a Sub named ReceivingMessage, but it only appears to do this after the sub that sends the message finishes.

The SendMessage function is as follows

Public Function SendMessage(ByVal SendString As String) As Boolean
    Dim _Result As Boolean = False
    Dim _SendString As String = ""

    Try
        _Response = ""

        If Not _Connection Is Nothing AndAlso _Connection.Client.Client.Connected AndAlso Not _Connection.Stream Is Nothing Then
            Dim _Now As String = Format(CInt(Now.Day), "00") & "/" & Format(CInt(Now.Month), "00") & "/" & Format(CInt(Now.Year), "0000") & " " & Format(CInt(Now.Hour), "00") & ":" & Format(CInt(Now.Minute), "00") & ":" & Format(CInt(Now.Second), "00")

            _SendString = _Now & CmdSpcr & SendString & EndOfMessageString

            Dim buffer() As Byte = System.Text.Encoding.ASCII.GetBytes(_SendString)

            _Connection.Stream.Write(buffer, 0, buffer.Length)

            _Result = True
        End If

        _WaitingForResponse = True

        'Wait for a response here

        If _Response.StartsWith("Received ") And _Response.EndsWith(" Bytes - " & _SendString) Then
            _Result = True
        Else
            _Result = False
        End If
    Catch ex As Exception
        RaiseEvent DisplayMessage(ex.ToString, MsgBoxStyle.Critical, "Error")
        _Result = False
    End Try

    Return _Result
End Function

The ReceivingMessage sub is very simple and is called as part of another class

Private Sub ReceivingMessage(ByVal message As String)
    If _WaitingForResponse Then
        _Response = message
    Else
        RaiseEvent MessageReceived(message)
    End If
End Sub

Here is the class

Imports System.Net.Sockets
Imports System.Net

Public Class modConnectionInfo
    Private _ReceivingMessageMethod As Action(Of String)
    Private _Buffer(9999) As Byte
    Private _Client As TcpClient
    Private _LastReadLength As Integer
    Private _Stream As NetworkStream

    Public ReadOnly Property ReceivingMessageMethod() As Action(Of String)
        Get
            Return _ReceivingMessageMethod
        End Get
    End Property

    Public ReadOnly Property Client() As TcpClient
        Get
            Return _Client
        End Get
    End Property

    Public ReadOnly Property Stream() As NetworkStream
        Get
            Return _Stream
        End Get
    End Property

    Public ReadOnly Property LastReadLength() As Integer
        Get
            Return _LastReadLength
        End Get
    End Property

    Public Sub AwaitData()
        _Stream.BeginRead(_Buffer, 0, _Buffer.Length, AddressOf DoReadData, Me)
    End Sub

    Public Sub Close()
        If _Client IsNot Nothing Then _Client.Close()

        _Client = Nothing
        _Stream = Nothing
    End Sub

    Private Sub DoReadData(ByVal result As IAsyncResult)
        Dim info As modConnectionInfo = CType(result.AsyncState, modConnectionInfo)

        Try
            If info._Stream IsNot Nothing AndAlso info._Stream.CanRead Then
                info._LastReadLength = info._Stream.EndRead(result)

                If info._LastReadLength > 0 Then
                    Dim message As String = System.Text.Encoding.ASCII.GetString(info._Buffer, 0, info._Buffer.Count)
                    message = message.Replace(vbNullChar, "")
                    info._ReceivingMessageMethod(message)
                End If

                ReDim info._Buffer(9999)
                info.AwaitData()
            End If
        Catch ex As Exception
            info._LastReadLength = -1
            info._ReceivingMessageMethod(ex.Message)
        End Try
    End Sub

    Public Sub New(ByVal address As IPAddress, ByVal port As Integer, ByVal ReceivingMessage As Action(Of String))
        _ReceivingMessageMethod = ReceivingMessage
        _Client = New TcpClient
        _Client.Connect(address, port)
        _Stream = _Client.GetStream
    End Sub
End Class

Does anyone know how I can get the SendMessage sub to pause at the part where I've put "'Wait for a response here" and allow the ReceivingMessage sub to run before continuing?

The way this class is called is as follows

_Connection = New modConnectionInfo(IPAddress.Parse(ServerIP), CInt(ServerPort), AddressOf ReceivingMessage)

If _Connection.Client.Client.Connected Then
    _Connected = True
End If

_Connection.AwaitData()

Any help would be greatly appreciated

Ste Moore
  • 107
  • 1
  • 10
  • This is how send and receive should work :). But how you will solve this is by using some state variable. Once you receive the data in receive method, you should parse and analyse the data. If after parsing, you think your code state has change, then call the function that will respond to that state change. – Ritesh Dec 04 '15 at 16:06
  • Thanks for the suggestion. The reason I'm doing it this way is because this class is being created from a Form. In the form the SendMessage function is being called to send a message to the server by If _Class.SendMessage("Command") = False Then Exit Sub. This way I can see if the command has been processed and received a response. I'm not sure how I can achieve this since it seems to wait until after the function has finished before running the ReceivingMessage sub. – Ste Moore Dec 04 '15 at 16:14

0 Answers0