Forum Discussion

MulgraveTester's avatar
MulgraveTester
Frequent Contributor
9 years ago

Please help with VBScript UDP Server

I need to send/receive UDP to my tested app to verify that the correct packets are sent and the GUI behaves correctly. I've tried to convert the JScript example into the following VBScript. It binds to the socket but always returns an empty array of data.

Wireshark shows that each packet is 15 bytes long. receiveLength returns the value 15 but binaryArray remains an array of zeros. Also, socket.available is always 0 when I would expect it to match receiveLength.

 

Can you please tell me where I am going wrong? Have I defined the byte array incorrectly or am I reading the data from the socket incorrectly?

 

The PC sending the data is a physically different PC to the one where TestComplete is running.

 

sub UDPServer()
  'Converted from JScript example: https://support.smartbear.com/viewarticle/9005/
  dim address, port, receiveTimeout, socket, broadcast, endpoint, byteType, binaryData, maxLength, receivedLength
  dim byteStr, str
  myAddress = "0.0.0.0"  
  myPort = 13004
  receiveTimeout = 15000

 

  'Define the socket

  set socket = dotNET.System_Net_Sockets.Socket.zctor( _
        dotNET.System_Net_Sockets.AddressFamily.InterNetwork, _
        dotNET.System_Net_Sockets.SocketType.Dgram, _
        dotNET.System_Net_Sockets.ProtocolType.Udp)      
  set project.Variables.openSocket = socket 'Handle for onStopTest event handler to close socket (in case of execution error)
  socket.ReceiveTimeout = receiveTimeout
  socket.Blocking = true
  'Define and bind to the Endpoint         
  set IPAddressObj = dotNET.System_Net.IPAddress.Parse(myAddress)
  set endpoint = dotNET.System_Net.IPEndPoint.zctor_2(IPAddressObj, myPort)
  socket.Bind(endpoint)
  'Create the byte array to receive data into
  maxLength = 256
  set byteType = dotNET.System.Type.GetType("System.Byte")
  binaryData = dotNET.System.Array.CreateInstance(byteType, maxLength)

  'Test if there is data then read that data

  bytesAvailable = socket.Available 'Returns 0
  receivedLength = socket.Receive(binaryData) 'Returns 15 - Matches Wireshark length. But binaryData is (0,0,0...)

  'Log the data received

  log.message("Bytes available: " & bytesAvailable)
  log.Message("Bytes received: " & receivedLength)
  byteStr = ByteArrayToHexString(binaryData, receivedLength, "")

  str = dotNET.System_Text.ASCIIEncoding.get_ASCII().GetString(binaryData)
  Log.Message(receivedLength & "/" & bytesavailable & " bytes were received: " & byteStr & "String Value: " & str)

  'Close the socket

  socket.Close()

end sub

 

function ByteArrayToHexString(byteArray, byteCount, prefix)
  dim i
  ByteArrayToHexString = ""

  for i = 0 to ubound(byteArray)
    ByteArrayToHexString = ByteArrayToHexString & prefix & byteArray(i) & " "
    i = i + 1
  next
end function

 

  • MulgraveTester's avatar
    MulgraveTester
    9 years ago

    Thanks to Evgeny at SmartBear Customer Care this is now resolved. A "Set" statement was required when defining the array so that an array object was created instead of an array. In case anyone else is trying to achieve the same aim the code now looks like this:

     

    sub UDPReceive()
      'Converted from JScript example: https://support.smartbear.com/viewarticle/9005/
      dim address, port, receiveTimeout, socket, endpoint, byteType, _
            byteData, maxLength, receivedLength, byteStr, addressObj
      address = "0.0.0.0" 
      port = 13004
      receiveTimeout = 15000
     
      'Create the byte array to receive data into
      maxLength = 256
      set byteType = dotNET.System.Type.GetType("System.Byte")
      Set byteData = dotNET.System.Array.CreateInstance(byteType, maxLength)

     

      'Define the socket
      set socket = dotNET.System_Net_Sockets.Socket.zctor_2( _
                  dotNET.System_Net_Sockets.AddressFamily.InterNetwork, _
                  dotNET.System_Net_Sockets.SocketType.Dgram, _
                  dotNET.System_Net_Sockets.ProtocolType.Udp)
      
      socket.ReceiveTimeout = receiveTimeout
       
      'Define and bind to the Endpoint           
      set addressObj = dotNET.System_Net.IPAddress.Parse(address)
      set endpoint = dotNET.System_Net.IPEndPoint.zctor_2(addressObj, port)
      socket.Bind(endpoint)
     
      'Read the data
      on error resume next
      receivedLength = socket.Receive(byteData) 'An exception occurs if no data is received
      if err.number <> 0 then receivedLength = 0
      on error goto 0 'turn off error handling
     
      'Close the socket
      socket.Close()

     

      'Log the data received
      byteStr = ByteArrayToHexString(byteData.oleValue, "")
      Log.Message(receivedLength & " bytes were received: " & byteStr)  

    end sub

    '-----------------------------------------------------------------------------------------------
    function ByteArrayToHexString(byteArray, prefix)
      dim i
      ByteArrayToHexString = ""

      for i = 0 to ubound(byteArray)
        ByteArrayToHexString = ByteArrayToHexString & prefix & right("0" & hex(byteArray(i)), 2) & " "
      next
    end function

  • I've never tried it myself, but I don't think VBScript (as standard) is too good with Byte Arrays ...

     

    More info here: https://groups.google.com/forum/#!topic/microsoft.public.scripting.vbscript/1OhVCKXHdcg

     

    This kind of makes sense to me. I've never actually tried to use Byte data types in VBScript. But if I read a Byte field from a SQL DB using VBScript I have to parse the data into something meaningful as the results value in VBScript does not match the SQL value correctly.

     

    BUT ... you are also using the dotNET assembly. And I'm not sure how that affects VBScript's ability to create and interact with Byte Arrays. Suspect staff or someone who has used it in the past will be better placed to help out ...

  • I have not played around with any of this, but what would happen if you were to read a value from the dotNET Byte Array using the method GetValue()?  (if I'm reading the docs correctly...)  Can you see the data that way?

     

    Refer to a similar post:  script based TCP IP client

    • MulgraveTester's avatar
      MulgraveTester
      Frequent Contributor

      Thanks Joseph but GetValue fails for me and when I go to the help it tells me that it is obsolete.

       

      I am not convinced that this is a data type issue but that was just one thought as to why I am not seeing the data being received. If anyone else has experience with sending/receiving data using VBScript I would be happy to hear from you.

       

      Cheers.

      • MulgraveTester's avatar
        MulgraveTester
        Frequent Contributor

        Thanks to Evgeny at SmartBear Customer Care this is now resolved. A "Set" statement was required when defining the array so that an array object was created instead of an array. In case anyone else is trying to achieve the same aim the code now looks like this:

         

        sub UDPReceive()
          'Converted from JScript example: https://support.smartbear.com/viewarticle/9005/
          dim address, port, receiveTimeout, socket, endpoint, byteType, _
                byteData, maxLength, receivedLength, byteStr, addressObj
          address = "0.0.0.0" 
          port = 13004
          receiveTimeout = 15000
         
          'Create the byte array to receive data into
          maxLength = 256
          set byteType = dotNET.System.Type.GetType("System.Byte")
          Set byteData = dotNET.System.Array.CreateInstance(byteType, maxLength)

         

          'Define the socket
          set socket = dotNET.System_Net_Sockets.Socket.zctor_2( _
                      dotNET.System_Net_Sockets.AddressFamily.InterNetwork, _
                      dotNET.System_Net_Sockets.SocketType.Dgram, _
                      dotNET.System_Net_Sockets.ProtocolType.Udp)
          
          socket.ReceiveTimeout = receiveTimeout
           
          'Define and bind to the Endpoint           
          set addressObj = dotNET.System_Net.IPAddress.Parse(address)
          set endpoint = dotNET.System_Net.IPEndPoint.zctor_2(addressObj, port)
          socket.Bind(endpoint)
         
          'Read the data
          on error resume next
          receivedLength = socket.Receive(byteData) 'An exception occurs if no data is received
          if err.number <> 0 then receivedLength = 0
          on error goto 0 'turn off error handling
         
          'Close the socket
          socket.Close()

         

          'Log the data received
          byteStr = ByteArrayToHexString(byteData.oleValue, "")
          Log.Message(receivedLength & " bytes were received: " & byteStr)  

        end sub

        '-----------------------------------------------------------------------------------------------
        function ByteArrayToHexString(byteArray, prefix)
          dim i
          ByteArrayToHexString = ""

          for i = 0 to ubound(byteArray)
            ByteArrayToHexString = ByteArrayToHexString & prefix & right("0" & hex(byteArray(i)), 2) & " "
          next
        end function