boris.nihil 0 Posted July 17 Hello I have question about indy,sending and receiving messages from-to ECR-POS(Ingenico), am i doing it right ? ------send to POS request for Card paying IdTCPClient1.IOHandler.InputBuffer.Clear; IdTCPClient1.IOHandler.Write(buff); Timer4.Enabled := true; ---------on timer4 try if IdTCPClient1.IOHandler.InputBufferIsEmpty then begin if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then begin bajt := IdTCPClient1.IOHandler.ReadByte; bajt := IdTCPClient1.IOHandler.ReadByte; IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt - 1,true); s := ''; for i := 0 to bajt - 1 do s := s + chr(buffer); Memo1.Lines.Add(s); Timer4.Enabled := false; end else IdTCPClient1.IOHandler.InputBuffer.Clear end else IdTCPClient1.IOHandler.InputBuffer.Clear; except end; Share this post Link to post
Remy Lebeau 1330 Posted July 17 (edited) 5 hours ago, boris.nihil said: I have question about indy FYI, there is an Indy-specific forum on this site: https://en.delphipraxis.net/forum/35-indy/ 5 hours ago, boris.nihil said: sending and receiving messages from-to ECR-POS(Ingenico), am i doing it right ? It is hard to answer that without knowing any details about the particular specification you are coding against. 5 hours ago, boris.nihil said: IdTCPClient1.IOHandler.InputBuffer.Clear; IdTCPClient1.IOHandler.Write(buff); Timer4.Enabled := true; If you are expecting a response immediately after writing, then why are you using a Timer? Just read and let it block. If you are doing this from the main UI thread and don't want to block the UI, then use a worker thread. Quote if IdTCPClient1.IOHandler.InputBufferIsEmpty then begin if IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then begin ... end else IdTCPClient1.IOHandler.InputBuffer.Clear end else IdTCPClient1.IOHandler.InputBuffer.Clear; Why do you keep clearing the IOHandler.InputBuffer when it is already empty? Quote bajt := IdTCPClient1.IOHandler.ReadByte; bajt := IdTCPClient1.IOHandler.ReadByte; IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt - 1,true); s := ''; for i := 0 to bajt - 1 do s := s + chr(buffer); Memo1.Lines.Add(s); Timer4.Enabled := false; Why are you discarding the 1st byte? What does it represent? FYI, you can replace your entire loop with a single call to Indy's BytesToString() function, eg: var Buffer: TIdBytes; ... IdTCPClient1.IOHandler.ReadBytes(Buffer, bajt - 1, False); s := BytesToString(Buffer); Or, you could just use IOHandler.ReadString() instead of IOHandler.ReadBytes(), eg: s := IdTCPClient1.IOHandler.ReadString(bajt - 1); Edited July 17 by Remy Lebeau Share this post Link to post
boris.nihil 0 Posted July 17 Quote FYI, there is an Indy-specific forum on this site: https://en.delphipraxis.net/forum/35-indy/ thanks Quote It is hard to answer that without knowing any details about the particular specification you are coding against. Datagram protocol Datagram protocol is used over stream-oriented protocols (TCP) to provide information to the receiver of the length of the data being sent. Datagram protocol forms a packet by adding a header to the payload. Datagram protocol header contains the length of the payload encoded in two bytes. Header Format Header consists of two bytes with the most significant byte first: Byte Value 1 Message length/256 2 Message lengt%256 --------------------------------------- Length of data Header Packet 7 0x00 0x07 0x00 0x07 B1 B2 B3 … B7 17 0x00 0x11 0x00 0x11 B1 B2 B3 … B17 135 0x00 0x87 0x00 0x87 B1 B2 B3 … B135 Quote If you are expecting a response immediately after writing, then why are you using a Timer? i need timer (put on 2000 ms), becouse i wait for customer to insert credit card on POS terminal, then POS will sent some message to me,starting with 10xxxxxxx Quote Why are you discarding the 1st byte? What does it represent? first 2 bytes is size of packet,i think first one is always zero ? Quote FYI, you can replace your entire loop with a single call to Indy's BytesToString() function, eg: thanks,i will try it Share this post Link to post
Remy Lebeau 1330 Posted July 17 (edited) 2 hours ago, boris.nihil said: Datagram protocol header contains the length of the payload encoded in two bytes. In that case, your code logic is wrong. You are throwing away one of the length bytes, so you will only be able to handle packets up to 256 bytes max. And, based on the examples provided, you should not be subtracting -1 from the length, either. You are ignoring the last byte in the payload. Try this instead: var s: string; len: UInt16; ... try if IdTCPClient1.IOHandler.InputBufferIsEmpty then begin if not IdTCPClient1.IOHandler.CheckForDataOnSource(1000) then Exit; end; len := IdTCPClient1.IOHandler.ReadUInt16; s := IdTCPClient1.IOHandler.ReadString(len); Memo1.Lines.Add(s); Timer4.Enabled := false; except end; 2 hours ago, boris.nihil said: i need timer (put on 2000 ms), becouse i wait for customer to insert credit card on POS terminal, then POS will sent some message to me,starting with 10xxxxxxx Fair enough, though I would still not advise doing that on the main UI thread to begin with. 2 hours ago, boris.nihil said: first 2 bytes is size of packet,i think first one is always zero ? Only for packets with payloads up to 255 bytes in size. Larger payloads will not have a zero as the 1st byte. This protocol allows for payloads up to 65535 bytes in size. Edited July 17 by Remy Lebeau Share this post Link to post
boris.nihil 0 Posted July 18 Quote len := IdTCPClient1.IOHandler.ReadUInt16; compiler says error,no such function this code works... ------------------- bajt := data1.IdTCPClient1.IOHandler.ReadByte; bajt1 := data1.IdTCPClient1.IOHandler.ReadByte; bajt2 := bajt * $10 + bajt1; data1.IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt2,false); s := ''; for i := 0 to bajt2 - 1 do s := s + inttohex(buffer,2); ---------------------------- i need a hex, I explode it with 1C delimeter, its easy to handle.. What AApend parameter means, true or false, what to use in: data1.IdTCPClient1.IOHandler.ReadBytes(Buffer,bajt2,false); ? Share this post Link to post
Remy Lebeau 1330 Posted July 19 12 hours ago, boris.nihil said: compiler says error,no such function Then you are using an outdated version of Indy and should upgrade. The ReadUInt16() method was added almost a decade ago, in Delphi XE8. In the meantime, you can use the older ReadWord() method instead. Quote bajt2 := bajt * $10 + bajt1; That calculation is wrong. You need to multiple by 256 ($100), not by 16 ($10). Better to just use ReadWord()/ReadUInt16() instead. 12 hours ago, boris.nihil said: 12 hours ago, boris.nihil said: What AApend parameter means, true or false, True means it will append the read bytes to the end of the TIdBytes. False means it will store the read bytes at the beginning of the TIdBytes, and will grow the TIdBytes if it is too small. Share this post Link to post