Sign in to follow this  
Followers 0
Kneel

Packet-based TCP comms Helper

1 post in this topic

If you are talking using text based protocols, Kip's TCP.au3 event driven UDF is great. But what happens if you want to talk to a 3rd party providers device/software that talks using binary format data in packet form? What if the packet size is variable? PTCP is a wrapper around Kip's TCP.au3 that lets you focus on dealing with the packets, rather than figuring out how to determine if there is a complete packet available etc.
 For sending, you just send a binary string (the actual packet data)

 For receiving, you just get a complete packet - even if the packet size is variable!

How? When you connect, you pass an AutoIt expression that tells PTCP how to tell if a packet is complete. For fixed sized packets, that's easy - just pass the number of bytes. For variable length packets, the expression can contain references to the packet data itself, as well as the number of bytes currently in the Rx buffer. This means you can specify the packet size as some combination of bytes in the packet.

An example might be: "($iAvail>7)?((BitAND(BinaryMid($aPacket,7,1), '0xff'))+(BitShift(BitAND(BinaryMid($aPacket,8,1),'0xff'),-8))+8):(0)"

This says: we need at least 8 bytes of the packet to know the packet size; once we have these 8 bytes, the packet size is stored in bytes 7 & 8 as little-endian (LSB first)

Other than the packetizing details, it's pretty much just Kip's event driven TCP code.

Hope you find it useful.

PTCP.au3

Share this post


Link to post
Share on other sites



Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0

  • Similar Content

    • Turtlix21
      TCP, UDP problem with receiving data
      By Turtlix21
      I've a problem with receiving data on my PC by TCP and UDP. I can send data to another computer, but can't receive it.
      I'm not shure where is the problem (on PC or on "another comupers")
      This is client code:
      ;TCP client TCPStartup() $socket = TCPConnect("192.168.0.18", 7777) ;try to connect to server and save number of socket If $socket = -1 Then ;if $socket = -1 then error MsgBox(16, "Error:", "Can't connect to server") EndIf $sendedBytes = TCPSend($socket, "nothing here :)") ;send message to connected socket If $sendedBytes = 0 Then ;if receiving data TCPSend(...) = 0 then error MsgBox(16, "Error", "Can't send message") EndIf TCPCloseSocket($socket) TCPShutdown() and server code:
      ;TCP server TCPStartup() $mainsocket = TCPListen("192.168.0.18", 7777) ;making main receiving socket While 1 ;receiving loop $acceptedSocket = TCPAccept($mainsocket) ;possible connection to accept If $acceptedSocket <> -1 Then $receivedData = TCPRecv($acceptedSocket, 1024) ;if main socket is connected then receive message MsgBox(64, "Received message!", "Message: " & $receivedData) TCPCloseSocket($acceptedSocket) ;close open connecion EndIf WEnd TCPShutdown()  
      When server is on PC I can't receive any messages from any other computers.
      When client is on PC I can receive messages on any another computer.
      I tried to turn off antiviruses and windows firewall but it did't change anything
       
      EDIT:
      Error code from client from TCPConnect is 10060 (connection time out) and from TCPSend: 10038
      I've found something about 10060 error code, Microsoft says "Connection timed out. A connection attempt failed because the connected party did not properly respond after a period of time, or the established connection failed because the connected host has failed to respond."
      So it means that the problem is with time of response but it makes no sense couse "another computer" is Virtual Machine with bridge internet connection from PC (pings beetwen PC  and VM are lower than 1ms.
      About 10038 error code microsoft says that this is problem with socket and it actually makes sense.
       
    • Blank517
      _SQLite_FetchData problem
      By Blank517
      Hi, when a client sends /logout to the server i want that the server find the id of the client and set his online status to 0
      Using 'default' I have no problems, but when I do this with 'blank517' gives me id 10 and then for the database remains online
      Database while Blank517 logout:
      id  |  username  |  password |   permissions  |  online  |
      0   |  default        |    pass1      |           0             |      0       |
      1   |  Blank517    |     pass       |           0              |     1       |
      Server recv:
      Func _Recv_From_Sockets_() For $0 = 1 To $max_connections $Recv = TCPRecv ($Socket_Data[$0][0],1024) If StringLeft($Recv, 1) = "/" Then If StringInStr($Recv, "logout") Then _SQLite_Query(-1, "SELECT id FROM Users WHERE username = '" & $Socket_Data[$0][1] & "' AND online = '1';", $hQuery) While _SQLite_FetchData($hQuery, $aRow) = $SQLITE_OK $sMsg &= $aRow[0]; <-- $sMsg = 10 after FetchData WEnd _SQLite_Exec(-1, "UPDATE Users SET online = '0' WHERE id = '" & $sMsg & "';") For $000 = 1 To $max_connections TCPSend($Socket_Data[$000][0], $Socket_Data[$0][1] & " ha effettuato il logout") Next TCPCloseSocket($Socket_Data[$0][0]) $sMsg = Null EndIf Else _Broadcast_To_Sockets_ ($Recv) EndIf Next EndFunc *excuse me for my bad english *
    • LuuQuangICT
      Send message using TCP in autoIT is not work
      By LuuQuangICT
      Hello every body! I am trying to dev an simple chat using TCP. but it don't work for me. Please help me.
      I want to in 1 second, Client will send to server a message. And then, Server recv this message and write to Console. But when i run server and client. In server, i was recv only one message. Please tell me why?
      In server, i code:
      #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Global $r = @CRLF; Global $ip = "127.0.0.1" Global $port = 1337 Global $client, $iSocket TCPStartup() $iSocket = TCPListen($ip, $port) While 1 $client = TCPAccept($iSocket) If $client <> -1 Then TCPSend($client, "Client is Connected"); EndIf $msg = TCPRecv($client, 1024) if StringLen($msg) <>0 Then ConsoleWrite("Server recv: " &$msg) EndIf TCPSend($client, "Send this msg to client"); Sleep(1000) WEnd In client, i code:
      #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <WindowsConstants.au3> Global $ip = "127.0.0.1" Global $port = 1337 Global $r = @CRLF; TCPStartup() $server = TCPConnect($ip, $port) While 1 TCPSend($server, "Send msg to server") Sleep(1000) WEnd  
    • toasterking
      Parsing binary data frames from an asynchronous source
      By toasterking
      I was just working on a project that involved decoding a stream of binary data from a serial port in AutoIt.  It took me a few hours to figure out how to process the data efficiently in AutoIt and I did not find any helpful examples on how to do so, so I thought I would share my core example and maybe save someone else some time.  There may be a more efficient way to do this, but this works well for me.
       
      #cs Author: ToasterKing This is an example of a way to parse streaming binary data that follows a strict format with a header and footer. In this example, each frame is 5 bytes with a 2-byte header of 0xD5AA and a 1-byte footer of 0xAD. The _BinaryParse() function accumulates incoming data in a buffer. Once a footer is found, it searches backward for the header, and if it is in the right position, it extracts the remaining 2 bytes in the middle, then moves on to looking for the next frame. #ce ; The data source might be something asynchronous like serial or TCP, but since this is just an example, I'm just putting the data in a variable. Local $fSomeData $fSomeData = Binary("0xD5AA24B1") ; Binary data constituting almost a complete frame. _BinaryParse($fSomeData) ; Call the function with the received data. It isn't a complete frame, so it is just stored in the buffer until more data is received. $fSomeData = Binary("0xAD62D5AA92E7AD") ; Remainder of the previous frame, one garbage byte (0x62) which should be skipped, and a complete additional frame. _BinaryParse($fSomeData) ; The function should be able to parse both frames now. Func _BinaryParse($fNewData) Local Static $fBinaryReceived = Binary("") ; Buffer for received data ConsoleWrite("Hey, the function is called!" & @CRLF) ; Add new data to the buffer. ; This ridiculous monstrosity is the only way I could find to append binary data to binary data in AutoIt. It must be converted to strings first. ; Both, one, or no substrings will begin with "0x" depending on whether they contained binary data. To be converted back to binary properly, only one instance ; of "0x" must exist at the beginning of the string. $fBinaryReceived = Binary("0x" & StringReplace(String($fBinaryReceived) & String($fNewData),"0x","")) ConsoleWrite("Data in the buffer: " & String($fBinaryReceived) & @CRLF) Local $iLength = BinaryLen($fBinaryReceived) ; Count the bytes in the data If $iLength > 0 Then Local $fBinaryReceivedTemp = $fBinaryReceived ; Create temporary copy to work on Local $fByte1,$fByte2 For $i = 1 To $iLength If BinaryMid($fBinaryReceivedTemp,$i,1) = 0xAD Then ; If the 1-byte footer found ConsoleWrite("Footer found at end of " & $i & " of " & $iLength & " bytes!" & @CRLF) If BinaryMid($fBinaryReceivedTemp,$i - 4,1) = 0xD5 And BinaryMid($fBinaryReceivedTemp,$i - 3,1) = 0xAA Then ; and the 2-byte header is found 4 bytes before that ConsoleWrite("Header found before the footer!" & @CRLF) $fByte1 = BinaryMid($fBinaryReceivedTemp,$i - 2,1) ; Get 1st byte in the body (between header and footer) $fByte2 = BinaryMid($fBinaryReceivedTemp,$i - 1,1) ; Get 2nd byte in the body (between header and footer) ConsoleWrite("Here is the critical data: " & String($fByte1) & " " & String($fByte2) & @CRLF) ; Just display the 2 bytes for demonstration purposes. Normally, you'd do something more useful with it here. EndIf $fBinaryReceived = BinaryMid($fBinaryReceivedTemp,$i + 1) ; Truncate the original data to remove all of the bytes just processed, then continue processing $fBinaryReceivedTemp EndIf Next EndIf EndFunc  
    • topten
      Parental Filter
      By topten
      Hi I have an idea of creating a parental filter (freeware) , which will be protecting children from navigating to adult websites.  I want to ask, what is your opinion, how to do it best way?
      How to catch the traffic from the very beginning?
      For example if a user is starting IE or Firefox, or if he has some alternate BLABLA-browser - how can I catch the url before actual navigation to website, so that my script could first check if the website is ok, and then if it decides that the website is not ok, just block connection to this IP.
       
      Looking forward to your opinions, Great thanx in advance!