1

私は、互いに通信するために手作業で書かれたHTTP要求を使用するTCPクライアントとサーバーをC#で作成しています。私が持っている問題は、を使ってNetwork Streamから読むことです。これまでのところ、私は多くの方法を試しましたが、無駄です。StreamReaderでHTTP要求を読み取る

私のTCPクライアントからのリクエストは様々な形であります。

HTTP 1.0:

"POST /" +名+ "HTTP/1.0のデータベースを更新するために、要求は次のようになり(CRLFは私が"\r\n"文字列を表すために使用する定数です) "+ CRLF +" Content-Length: "+ length + CRLF + CRLF + location;

HTTP 1.1:

"POST/HTTP/1.1" + CRLF +ホスト名+ "のContent-Length:" +長さ+ CRLF + CRLF + nameLocString。

要求は正しい形式であり、クライアントは正しく送信しています。私は、問題なく問題に応答したアクセス権を持っているサーバーでこれをテストしました。

私の問題はTCPリスナーコードにあります。コード全体を投稿しないようにするには、問題のあるコードの部分だけを含めます(デバッグによって見つけ出した部分)。

Serverコード:

NetworkStream socketStream = new NetworkStream(connection); 
StreamReader sr = new StreamReader(socketStream); 

string input = ReadAllLinesWithNull(sr); // reading version 1 
string input = ReadAllLinesWithEndOfStream(sr); // reading version 2 
string input = ReadAllLinesWithPeek(sr); // reading version 3 
string input = sr.ReadToEnd(); // reading version 4 

、使用方法は以下のとおりです。読書のためのこれらのメソッドの

static string ReadAllLinesWithNull(StreamReader sr) 
{ 
    string input; 
    string nextLine; 
    input = sr.ReadLine(); 
    while ((nextLine = sr.ReadLine()) != null) 
    { 
     Console.WriteLine(input); 
     input += nextLine; 
    } 
    sr.Close(); 
    return input; 
} 

static string ReadAllLinesWithEndOfStream(StreamReader sr) 
{ 
    string input = ""; 
    while (!sr.EndOfStream) 
    { 
     input += sr.ReadLine(); 
    } 
    sr.Close(); 
    return input; 
} 

static string ReadAllLinesWithPeek(StreamReader sr) 
{ 
    string input = ""; 
    while (sr.Peek() >= 0) 
    { 
     input += sr.ReadLine(); 
    } 
    sr.Close(); 
    return input; 
} 

どれも働きました。接続タイムアウトが設定されていると、入出力の例外が発生しているので、接続が強制的に終了するまでに時間がかかっていました。私はタイムアウトをオフにし、Readには不確定な時間がかかりました。私はそれが最終的に2つのCRLF("\r\n\r\n")のクラスタがある場合に、ストリームリーダーは対処できないことが判明プロトコルとのすべてのバージョンでハング場所を選び出すことができたReadLine() Sを使用する

感謝これと一緒に立ち往生する。

これを回避する方法についてご意見はありますか?仕様にあるように、複数のCRLFを含むバージョンを使用する必要があります。

追加情報が必要な場合は、可能な限りssonとして提供するようにします。

+0

「これに対処できずに立ち往生できません」というコードを投稿することはできますか? 'ReadLine'には終端のリターンや改行は含まれていないことに注意してください(https://msdn.microsoft.com/en-us/library/system.io.streamreader.readline%28v=vs.110%29.aspx) 、あなたが投稿したものは、リターンと改行を取り除いて連結されたすべてのコンテンツを返します。 –

+0

@DourHighArch私が提供したコードは、すべてが失敗しているコードです。私はチェックし、クライアントは正しくストリームに記載されているHTTP要求を書き込み、それらをフラッシュし、私はReadLineメソッドのいずれかを使用して読むと、Content-Length:+ length + CRLF + CRLFを超えたものは得られません。タイムアウトが設定されていると、無期限に読み込まれるか、例外がスローされます。 ReadLineについてのご注意ありがとうございます。最初はできるだけシンプルに読んで、後で正しい読みを見たいと思っていました。私は新しい単純なサーバー(ちょうど読んでエコー)で読書をテストし、それは同じ問題を抱えていた。 –

答えて

2

最後に私は私の問題の解決策を見つけました。代わりに、私は

static string ReadAllLinesWithPeek(StreamReader sr) 
{ 
    string input = ""; 
    while (sr.Peek() >= 0) 
    { 
     input += (char) sr.Read(); 
    } 
    return input; 
} 

を使用していた

static string ReadAllLinesWithPeek(StreamReader sr) 
{ 
    string input = ""; 
    while (sr.Peek() >= 0) 
    { 
     input += sr.ReadLine(); 
    } 
    sr.Close(); 
    return input; 
} 

を使用しての私はまだラインで入力を読み込むには機能しなかった理由はわからないが、時間のcharでそれを読むとき、それはありません。 Read操作に

+0

ありがとう、今日は私の一日を救った:D –

1

NetworkStreamブロックが現在データなしであり、他方の側がまだそのチャネルを閉じていない場合。 TCP自体にはというメッセージという概念はありません。その問題はHTTPレベルで解決されるはずです。

HTTPの場合、データに\r\n\r\nというシーケンスが含まれていると、ヘッダーと本文が分かれるまで読むことができます。体を処理する方法存在するヘッダに依存します。

  • Transfer-Encoding: chunkedは、送信側がデータのチャンクを送信し、ないときは存在すべきであり、長さ0のチャンク
  • Content-Lengthで終了することを示します上記のヘッダが設定されていない場合はチャンクを使用して、あなたがして体を持つべきではないデータ
  • GETリクエストの正確多くのバイトを読み取ることができ、あなたはおそらくこれを引き受けることができ
  • Connection: closeは、すべての応答データはあなたが見ることができるよう

は、StreamReader.ReadLine()はヘッダを解析にかなりよく働くだろう送信された後、接続がクローズされることを示し、応答のために使用することができる、そしてそれは非常に適していますチャンクも読んでいますが、固定長のボディの読み込みには使用できません。

StreamReaderによって読み込まれたストリームから読み取るのがどれほど現実的ではないかわかりませんが(バッファにデータを先読みしている可能性があります)、その周囲のusingブロックを叩くと、 pick that one constructor overloadを除き閉鎖してください。

+0

私は以前は間違っていたので、私はあなたの答えを受け入れなかった。それに続いて、私の問題はちょうどその行の下に移動しました。あなたの努力に感謝し、私の質問への答えを書いてくれてありがとう。 –

+0

私はあなたが私の答えを受け入れることを気にしませんが、以前は、この回答があなたに 'StreamReader 'を呼び掛けてくれたとコメントしました。'using'ブロックを使用する代わりにClose()を使用します。これは実際に私があなたに送りたい方向ではありません。私の答えに関する質問がある場合、あなたはそれらをコメントすることができます。 –

関連する問題