2010-11-18 10 views
2

私はdelphiを初めて使っています。これが私の最初のプロジェクトです。私は、ローカルネットワークに接続されたデバイスを持っているIdTCPClient.IOHandler.ReadStream()!が正常に終了しました。

procedure TForm1.Button2Click(Sender: TObject); 
responseStringFromServer:TStringStream; 
begin 
try 
    if IdTCPClient1.Connected then 
    begin 
    dataSentToDevice:= 'http/1.0 content-length: 344 content-type: text/xml <?xml   version="1.0" encoding="UTF-8" ?> ...' 
    IdTCPClient1.IOHandler.WriteLn(dataSentToDevice); 
    responseStringFromServer := TStringStream.Create; 
    IdTCPClient1.IOHandler.ReadStream(responseStringFromServer); 
    ... 

: は、ここでは、コードの少しです。私はそれに成功して接続することができます。送信コマンドは、あまりにも取り組んでいるが、私は

IdTCPClient1.IOHandler.ReadStream(responseStringFromServer); 

を行うとき、それは、デバイスが処理を行われ、例外が発生したゴマ待つ:「接続クローズ優雅に」。だから私は、デバイスが私に送ることになっているデータを読み取ることができません。デバイスがシャットダウンしていません。私は他の投稿を読んだことがあり、そのデバイス自体が接続を切断することを理解しています。

私はそれと通信するデモプログラムを持っており、正常に動作します。私はそれが接続をドロップする前に応答xmlを取得する必要があります。

また、リクエストはhttpで、私はIdTCPClientを使用しています(xmlリクエストを使用する必要があります。私はTidHTTPでそれを行う方法を知らない)。 デバイスが応答を送信した後、接続を切断して、データを受信する前にtcpclientの接続が切断されたことを示すことがあります。

助けていただけたら幸いです!

+0

正常に動作するデモプログラムがある場合は、ネットワークスニファ(WireShark)を使用してその動作を確認し、通信フローとDelphiアプリケーションを比較します。ドンのプロキシhttp://donsproxy.moneybender.com/のようなHTTPプロキシも使用できます - ネットワークスニッフィングより簡単かもしれません。 – mjn

+0

合意。デバイスの実際のプロトコルに関するドキュメントがない場合は、パケットスニッファが次善策です。 –

答えて

1

はまた、要求がhttpと私はIdTCPClientを使用して います(私は、XML 要求を使用する必要がある、私はTidHTTPでそれを を行う方法を知りません)。 IdHTTPでの作業

は簡単です...

  1. フォームにそのインスタンスをドロップし、それを選択 。オブジェクトインスペクタで
  2. は、 はprotocolVersionプロパティに移動し、それ はその
  3. リクエストプロパティセットを開き、pv1_0に設定され、text/xmlでの Request.ContentType、およびUTF-8へ Request.ContentEncodingを設定しました、 を入力し、 が必要な場合は他のプロパティを設定します。
  4. フォームにボタンを追加し、 をダブルクリックします。
  5. コードで TStringStreamのインスタンスを作成し、XML のコンテンツをそこにロードします。
  6. ストリームを IdHttp.Request.Sourceに割り当てます。
  7. にホストアドレスを指定してIdHttp.Get()メソッドを呼び出します。
  8. IdHttp.Get()は、サーバーが送信した応答である という文字列を返します。
+0

UTF-8は有効なContentEncodingプロパティ値ではありません。代わりにCharSetプロパティを考えています。また、Request.Streamプロパティもありません。代わりに、入力ストリームをそのままPOST()のASourceパラメータに渡します(入力データをGETリクエストで送信するには、DoRequest()を直接呼び出す必要があります)。また、TStringStreamの代わりにTMemoryStreamを使用することをお勧めします。なぜなら、TStringStreamはD2009でUnicodeをサポートするように変更されていて、XMLデータを偶然に邪魔したくないからです。 –

+0

ok、idhttpでデータを送信するとうまくいきます。それでも私はIdHttp.get()プロシージャでデバイスからデータを取得する際に問題があります。今度はIdHttp.get()で停止し、しばらく待ちます。それから、EIdConnClosedGracefully例外をスローします。データを要求する良い方法があるか、idhttp.get()が動作する方法はありますか? IdHTTP1.Get( 'http:// deviceIP:port'、response)を使用している瞬間です。応答はTMemoryStreamのタイプです。レスポンスの待機を停止する必要がある場合の戻り時間を指定する方法はありますか? – Peacelyk

+0

OK、判明したように、私は別のポートを聴かなければなりませんでした。私がデータを送っていたものではありません。しかし、まだそれは正常に動作していない:今私はidhttp.get()プロシージャを呼び出すときに、それだけでタイムアウトが発生するまでそこにとどまります。私はデータを送信する前にポートを聞いていなければなりませんか、データを送信した直後にポートをリッスンするのに十分でしょうか? – Peacelyk

2

ReadStream()を呼び出す方法では、最初の4バイト(またはTIdIOHandler.LargeStreamプロパティがTrueの場合は8バイト)を整数(またはInt64)としてネットワークバイト順に解釈します。データの長さを指定して、そのバイト数を読み込もうとします。デバイスは実際にそのような長さの値を送信していますか?そうでなければ、ReadStream()は間違ったバイト数の読み取りを試みます。 EIdConnClosedGracefully例外は、デバイスが最後にソケットを閉じることを意味します。そのため、デバイスはデータを送信した直後に接続を切断しているか、次のコマンドを送信するのを待っているうちにタイムアウトしています。前のコマンドの間違ったデータの待機をブロックしているため、

0

@Remyルボーと(自分の編集キャレットがReadStream文上でF1キーを押します)のドキュメントで言ったように:

AByteCountはAStreamに読み込まれるIOHandlerからのバイト数を示します。 AByteCountに-1があり、AReadUntilDisconnectにFalseが含まれている場合、バイト数はIOHandlerからInteger値として読み取られます。 AStreamのサイズは、IOHandlerから予想されるサイズに合わせて調整されます。

あなたはINDYクライアントによって期待どおりにそのバイトcoundを送信する場合、一端、他でReadStream、または他の言語でINDY WriteStreamにも書かれてサーバーに接続しているとき、これは非常に便利です。

のデバイスを読んでいる場合は、デバイスがその情報をストリームの先頭に送信しているか、データの読み方を変更していることを確認してください。ストリームのサイズを知っている場合は、2番目のパラメータ:AByteCountを渡します。ストリームが終了したときにデバイスがチャネルを閉じる場合は、-1を2番目のパラメータとして渡し、Trueを3番目のパラメータとして渡します。AReadUntilDisconnect。

既知のターミネータ(CR/LFなど)を使用してデバイスが不明な長さのテキストを送信する場合は、IOHandlerのReadLnメソッドを使用してその文字列を取得してください。

はどちらがニーズに合っていない場合を見てみましょう、デバイスによって送信されたデータを取得するための正しいものを見つけるためにTIOHandlerClassし、それぞれのRTFMの読む*方法について見てみましょう。

関連する問題