質問

ソケットを使用して簡単なSNPP(Simple Network Paging Protocol)クライアントを作成しようとしています。サーバー間の小さな不一致を除き、すべてがうまく機能しているようです。

コマンドを送信するとき、通常はデータの単一のチャンクである応答を読み取る必要があります。ただし、SprintのSNPPサーバーは2つの部分で応答を送信します。データの最初のチャンクは、ステータスコードの最初の数字です。 2番目のチャンクは残りです。たとえば、「220 Gateway ready」を受信しようとすると、返信、次のように届きます:

2

残りを取得するには、別の空のコマンドを送信する必要があります:

20 Gateway ready

今のところ、私は使用しています:

byte[] buffer = new byte[256];
socket.Receive(buffer);

データの各チャンクに個別のバッファを割り当てずに、コマンドを発行した後、利用可能なすべてのデータを確実に受信するにはどうすればよいですか?

役に立ちましたか?

解決

チャンク化された応答の場合、次のようなデータを読むことをお勧めします。

using (var resultStream = new MemoryStream())
{
    const int CHUNK_SIZE = 2 * 1024; // 2KB, could be anything that fits your needs
    byte[] buffer = new byte[CHUNK_SIZE];
    int bytesReceived;
    while ((bytesReceived = socket.Receive(buffer, buffer.Length, SocketFlags.None)) > 0)
    {
        byte[] actual = new byte[bytesReceived];
        Buffer.BlockCopy(buffer, 0, actual, 0, bytesReceived);
        resultStream.Write(actual, 0, actual.Length);
    }

    // Do something with the resultStream, like resultStream.ToArray() ...
}

他のヒント

Socket.Availableプロパティを確認して、Receiveを再度呼び出す必要があるかどうかを判断してください。

あなたの質問は理解できたと思います。 Socket.Receive のこのオーバーロードにより、指定する整数を渡すことができます。データの配置を開始するオフセット位置。例のように最初の呼び出しで1バイトを取得した場合、オフセット1でこのオーバーロードを呼び出し、同じバッファーを使用できます。

Socket.Receive は、受信したバイト数である整数を返します。これが1であるかどうかを確認して、 Receive を再度呼び出します。

byte[] buffer = new byte[256];
int len = socket.Receive(buffer);

if (len == 1)
  socket.Receive(buffer, 1, buffer.Length - 1, SocketFlags.None);

すべて、

ウェブサーバーが「チャンク」でデータを送信している場合各チャンクの長さ(16進値を示す文字列として)が先行します。

チャンクサイズ[;チャンク拡張子] チャンクデータ

eg:15バイトをチャンクする:

F; 123456789ABCDEF

ソケットからHTTPデータを受信する際の最大の問題は、読み取るデータ量を決定することです。使用可能なすべてのデータを受信し、Recieveメソッドを再度呼び出した場合、Recieveメソッドはリモートソケットがさらにデータを送信するまでブロックします。 HTTP / 1.0接続の場合は発生しません。

ソケットをラップするリーダーを実装する必要があります。バッファにデータを受信し、「ReadLine」を提供する必要があります; 13の後に10(CRLF)が読み取られるまでバッファーの内容を読み取るメソッド

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top