2012-03-07 19 views
5

Sto utilizzando le seguenti righe di codice per scrivere e leggere da un modem/router esterno (dispositivo noto) tramite IP.Indy TCPClient e byte errato in InputBuffer

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

MsgStr è un tipo di stringa che contiene il testo che sto inviando al mio dispositivo. Il buffer è dichiarato come TIdByte. Posso confermare che IOHandler.InputBufferIsEmpty restituisce True immediatamente prima di chiamare ReadBytes.

Mi aspetto che i primi 10 byte ricevuti siano molto specifici, quindi dal mio punto di vista sono interessato solo ai primi 10 byte ricevuti dopo aver inviato la mia stringa.

Il problema che sto avendo è, quando si parla di alcuni dispositivi, il primo byte restituito la prima volta ho mandato una stringa dopo aver stabilito una connessione mette un ladro di byte (casuale) nella mia uscita Buffer. I seguenti byte seguenti sono corretti.

ad esempio 10 byte mi aspetto potrebbe essere: # 6A1EF1090 # 3 ma ciò che ottengo è # 6A1EF1090.. in questo esempio ho un punto fermo dove non dovrebbe essercene uno.

Se tento di inviare nuovamente, funziona correttamente. (cioè la seconda scrittura inviata dopo che è stata stabilita una connessione). Ciò che è strano (per me) sta usando un Socket Sniffer non mostra il byte casuale che viene restituito. Se creo il mio "server" per ricevere la risposta e inviare qualcosa, funziona al 100% del tempo. Altri software, cioè non il mio software, comunicano perfettamente con il dispositivo (ma ovviamente non ho idea di come stanno analizzando i dati).

C'è qualcosa che sto facendo in modo errato al di sopra di quello che causerebbe questo - tenendo presente che si verifica solo la prima volta che sto usando Scrivi dopo aver stabilito una connessione?

Grazie

EDIT

sto usando Delphi 7 e Indy 10.5.8

UPDATE

OK. Dopo molti test e ricerche, non sono più vicino a trovare questa soluzione. Sto ottenendo due scenari principali. 1 - Primo byte mancante e 2 - byte "introdotto" all'inizio del pacchetto ricevuto. Usando TIdLogEvent e TIdLogDebug entrambi mostrano il byte mancante o il byte introdotto inizialmente come appropriato. Quindi la mia precedente affermazione su ReadBytes mostra costantemente ciò che Indy crede ci sia (secondo me).

Inoltre, per testarlo ulteriormente, ho scaricato e installato componenti ICS. Sfortunatamente (o fortunatamente a seconda di come la si guarda) questo non ha mostrato gli stessi problemi di Indy. Questo non mostrava il primo byte mancante né mostrava un byte introdotto all'inizio. Tuttavia, ho fatto solo test superficiali, ma Indy produce il comportamento "praticamente subito" mentre ICS non lo ha ancora prodotto.

Se qualcuno è interessato, posso fornire una piccola app dimostrativa che illustra il problema e l'IP a cui mi collego: è un IP pubblico, quindi chiunque può accedervi. Altrimenti per ora, dovrò solo aggirare il problema. Sono riluttante a passare a ICS come ICS potrebbe funzionare bene in questo caso e dato l'uso di questa roba di socket è praticamente l'intero nodo del programma, sarebbe brutto dover sostituire interamente Indy con ICS.

+0

Provare ad inviare un AnsiString (sizeof (char) = 1), che potrebbe aiutare – ComputerSaysNo

+1

Dove porrei che il codice? Cordiali saluti, ho modificato la mia domanda per mostrare le versioni di Delphi che sto usando nel caso in cui pensassi che stavo usando versioni successive di Delphi che usano Unicode. – Jason

+0

dovresti usare i tag per specificare la versione delphi – ComputerSaysNo

risposta

3

L'ultimo parametro (Vero)

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

provoca la lettura di accodamento anziché sostituire il contenuto del buffer.

Ciò richiede che la dimensione e il contenuto del buffer siano impostati correttamente per primi.

Se il parametro è False, il contenuto del buffer verrà sostituito per il numero specificato di byte.

+0

sfortunatamente impostandolo su False non fa alcuna differenza - se è questo che intendi. Ho anche provato varie combinazioni di SetLength (Buffer, 10) con True/False anche nel caso in cui ciò non ha aiutato. Ma date le opere Vere per ogni successiva invio/ricezione sarei stato sorpreso (felicemente seppur) se questo avesse funzionato. :) – Jason

1

ReadBytes() non iniettare byte canaglia nel buffer, quindi ci sono solo due possibilità mi viene in mente in questo momento dato le scarse informazioni che hai fornito:

  1. Il dispositivo in realtà è l'invio di un byte extra su connessione iniziale, come suggerito da mj2008. Se uno sniffer di pacchetti non lo rileva, prova a collegare uno dei componenti TIdLog... di Indy allo TIdTCPClient, ad esempio TIdLogFile o TIdLogEvent, per verificare che cosa sia effettivamente ricevuto dallo zoccolo TIdTCPClient.

  2. si ha un'altra lettura del thread dalla stessa connessione allo stesso tempo, corrompendo lo InputBuffer. Anche una chiamata a TIdTCPClient.Connected() eseguirà una lettura. Non eseguire letture in più thread contemporaneamente, se si stanno utilizzando i thread.

+0

Grazie. Proverò il pt 1 e vedrò se questo fornisce qualche intuizione e riferire. – Jason

Problemi correlati