4

現在のプロジェクトでは、tcp/ip ソケット接続を介して XML データを要求する必要があります。このために、私は TcpClient クラスを使用しています。

Dim client As New TcpClient()
client.Connect(server, port)

Dim stream As NetworkStream = client.GetStream()
stream.Write(request)
stream.Read(buffer, 0, buffer.length)

// Output buffer and return results...

現在、これは小さな応答に対してうまく機能します。しかし、より大きなデータ ブロックの受信を開始すると、データがソケット接続を介してバーストでプッシュされているように見えます。これが発生すると、stream.Read 呼び出しは最初のバーストのみを読み取るため、残りの応答を見逃してしまいます。

この問題を処理する最善の方法は何ですか? 最初は、有効な XML ドキュメントが作成されるまでループしようとしましたが、stream.Read 呼び出しの合間に、基になるストリームがシャットダウンされ、データの最後の部分を見逃すことがあることがわかりました。

4

4 に答える 4

3

読み取り用のループを作成します。

Stream.Read は、これまでに読み取ったバイト数に対して int を返します。ストリームの最後に達した場合は 0 を返します。

したがって、次のようになります。

int bytes_read = 0;
while (bytes_read < buffer.Length)
   bytes_read += stream.Read(buffer, bytes_read, buffer.length - bytes_read);

編集: さて、問題はバッファのサイズをどのように決定するかです。サーバーが最初にサイズを送信する場合は問題ありません。上記のスニペットを使用できます。ただし、サーバーが接続を閉じるまで読み取る必要がある場合は、try/catch (サイズがわかっている場合でもこれは良い考えです) を使用し、bytes_read を使用して受け取ったものを判断する必要があります。

int bytes_read = 0;
try
{
   int i = 0;
   while ( 0 < (i = stream.Read(buffer, bytes_read, buffer.Length - bytes_read) )
      bytes_read += i;
}
catch  (Exception e)
{
//recover
}
finally
{
if (stream != null)
   stream.Close();
}
于 2008-10-03T19:12:00.077 に答える
2

Read がストリームを完全に読み取ることは保証されていません。読み取った実際のバイト数を返し、読み取るバイトがそれ以上ない場合は 0 を返します。ループを続けて、ストリームからすべてのデータを読み取る必要があります。

于 2008-10-03T19:17:05.700 に答える
0

このようなタスクにはWCFを試してみることを強くお勧めします。それほど急ではない学習曲線の後、rawソケット通信に比べて多くの利点があります。手元のタスクについては、前の回答に同意します。ループを使用し、必要に応じて動的にメモリを割り当てる必要があります。

于 2009-05-04T10:33:17.413 に答える
0

これは、応答文字列を「応答」して取得するための可能な方法です。バイト配列が必要な場合は、ms.ToArray() を保存するだけです。

string response;

TcpClient client = new TcpClient();
client.Connect(server, port);
using (NetworkStream ns = c.GetStream())
using (MemoryStream ms = new MemoryStream())
{
    ns.Write(request);

    byte[] buffer = new byte[512];
    int bytes = 0;

    while(ns.DataAvailable)
    {
        bytes = ns.Read(buffer,0, buffer.Length);
        ms.Write(buffer, 0, bytes);
    }

    response = Encoding.ASCII.GetString(ms.ToArray());
}
于 2009-02-11T22:05:38.443 に答える