Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indy TCPClient and rogue byte in InputBuffer

I am using the following few lines of code to write and read from an external Modem/Router (aka device) via IP.

TCPClient.IOHandler.Write(MsgStr);
TCPClient.IOHandler.InputBuffer.Clear; 
TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

MsgStr is a string type which contains the text that I am sending to my device. Buffer is declared as TIdBytes. I can confirm that IOHandler.InputBufferIsEmpty returns True immediately prior to calling ReadBytes.

I'm expecting the first 10 bytes received to be very specific hence from my point of view I am only interested in the first 10 bytes received after I've sent my string.

The trouble I am having is, when talking to certain devices, the first byte returned the first time I've sent a string after establishing a connection puts a rogue (random) byte in my Buffer output. The subsequent bytes following are correct.

eg 10 bytes I'm expecting might be: #6A1EF1090#3 but what I get is .#6A1EF1090. in this example I have a full stop where there shouldn't be one.

If I try to send again, it works fine. (ie the 2nd Write sent after a connection has been established). What's weird (to me) is using a Socket Sniffer doesn't show the random byte being returned. If I create my own "server" to receive the response and send something back it works fine 100% of the time. Other software - ie, not my software - communicates fine with the device (but of course I have no idea how they're parsing the data).

Is there anything that I'm doing incorrectly above that would cause this - bearing in mind it only occurs the first time I'm using Write after establishing a connection?

Thanks

EDIT

I'm using Delphi 7 and Indy 10.5.8

UPDATE

Ok. After much testing and looking, I am no closer to finding this solution. I am getting two main scenarios. 1 - First byte missing and 2 - "introduced" byte at the start of received packet. Using TIdLogEvent and TIdLogDebug both either show the missing byte or the initial introduced byte as appropriate. So my ReadBytes statement above is showing consistently what Indy believes is there (in my opinion).

Also, to test it further, I downloaded and installed ICS components. Unfortunately (or fortunately depending on how you look at it) this didn't show the same issues as Indy. This didn't show the first byte missing nor did it show an introduced byte at the beginning. However, I have only done superficial testing, but Indy produces the behaviour "pretty much straight away" whereas ICS hasn't produced it at all yet.

If anyone is interested I can supply a small demo app illustrating the issue and IP I connect to - it's a public IP so anyone can access it. Otherwise for now, I'll just have to work around it. I'm reluctant to switch to ICS as ICS may work fine in this instance and given the use of this socket stuff is pretty much the whole crux of the program, it would be nasty to have to entirely replace Indy with ICS.

like image 579
Jason Avatar asked Oct 08 '22 11:10

Jason


2 Answers

The last parameter (True)

TCPClient.IOHandler.ReadBytes(Buffer, 10, True);

causes the read to append instead of replace the buffer content.

This requires that size and content of the buffer are set up correctly first.

If the parameter is False, the buffer content will be replaced for the given number of bytes.

like image 144
mjn Avatar answered Oct 13 '22 12:10

mjn


ReadBytes() does not inject rogue bytes into the buffer, so there are only two possibilities I can think of right now given the limited information you have provided:

  1. The device really is sending an extra byte upon initial connection, like mj2008 suggested. If a packet sniffer is not detecting it, try attaching one of Indy's own TIdLog... components to your TIdTCPClient, such as TIdLogFile or TIdLogEvent, to verify what TIdTCPClient is actually receiving from the socket.

  2. you have another thread reading from the same connection at the same time, corrupting the InputBuffer. Even a call to TIdTCPClient.Connected() will perform a read. Don't perform reads in multiple threads at the same time, if you are using the threads.

like image 32
Remy Lebeau Avatar answered Oct 13 '22 12:10

Remy Lebeau