2011-07-21 14 views
2

こんばんは事前に申し訳ありませんが、文字列のメッセージを受信するが、エラーがどこにあるか分かりません。一度にたくさんのものを転送したい(配列の内容、数百バイト)。非同期ソケット、</p> <p>私のクライアントアプリケーションが非同期にサーバから受信している...そんなにを書き込むため、

サーバから「コマンド」を送信し、クライアント側の機能がこれらのコマンドに従って動作するようにしたいとします。たとえば、サーバからのメッセージが"print_hello"の場合、helloを出力する関数を呼び出す必要があります。 。

データを非同期的に受信すると、データがどれだけ送信されたか(または予想以上のデータが送信されたかどうかはわかりません)、すべてのデータを"コマンドの終わり"(例えば、'!')符号を受信したときには、その関数を呼び出すことを知る必要があります。

これまでのところ私にとっては意味がありますが、実装には問題があります。私のDataReceivedコールバック関数では、私はこのコードを持っている:

Console.WriteLine("Raw data: {0}", data)); 
mainBuffer += data; 
Console.WriteLine(mainBuffer); 

mainBufferは、最初の行が正しく印刷さvolatile static string mainBuffer = ""; として宣言され、そして期待通りのデータのすべてを通過します。しかし、私がmainBufferを印刷すると、受信した最初のデータセットのみが出力され、残りはバッファに追加されません。

この原因は何ですか?スレッドの安全性の問題?私はmainBufferの最新の値を読んでいませんか?私はこれをデバッグするためにブレークポイントを使用することはできません。

サンプル出力:

Raw data: ABC 
ABC 
Raw data: DEF 
ABC 
RAW data: GHI 
ABC 

小さな更新は、私もvolatile static intを使用してみました、そして、それは各DataReceived()後に正しくインクリメントし、印刷します。文字列はまだ更新されません。

+0

mainBufferはどこで宣言しましたか?あなたはそれを受け取るたびにリセットしないのですか? " – Eiver

答えて

3

ここに問題があります"コードが煩雑です!"

//of course the problem has noting to do with the string being volatile... 
private volatile string mainBuffer = string.Empty; 

byte[] buffer = new byte[1024]; 

while (networkStream.Read(buffer, 0, buffer.Length) > 0) 
{ 
    string data = System.Text.Encoding.UTF8.GetString(buffer); 
    Console.WriteLine("Raw data: {0}", data)); 
    mainBuffer += data; 
    Console.WriteLine(mainBuffer); 
} 

もちろん、このコードの出力は前述のとおりです。

C#でstringクラスは、配列内の最初のcharへのポインタによってchar開始のアレイであり、特別な「端末」チャー\0によって終了:ここで起こっていることです。
nインデックスのバイト配列を作成すると、配列のすべてのインデックスがデフォルト値byte0)で埋め尽くされます。しかし0はちょうどあなたがRead(buffer)を呼び出すときに読んデータを単にに合うように、方法はバッファをトリミングしないなり、SO端子のcharに\0

byte b = (byte)`\0`;\\the value of b will be 0 

に等しいています。バッファサイズ "ここで1024"が読み込まれたデータより大きい場合、バッファの残りのバイトはすべて終端文字 '\ 0'と等しくなります。したがって、生成される文字列の配列はABC\0\0\0\0... to the index 1024になります。あなたはそれに文字列DEFを追加すると、それはchar配列は、その後ABC\0\0\0\0...DEFになります、「最後の\0後に」char配列の最後のインデックスでそれを追加しますが、理由のDEFは、端末のchar(s)はそうConsole.Write後に追加されます最初の後にすべて無視されます\0!あなたがデバッグ中

はまた、あなたがmainBuffer変数にマウスを指している場合、あなたはそれはしかし、問題を修正し、唯一の信頼できる文字列を生成するかもしれないABC\0\0\0\0..DEF\0\0\0\0..GHI

のようなものが含まれている実際のデータが表示されます、注意してください読み取られた実際のバイトを取得し、その文字列のみを生成します。だから、:

int dataRead = 0; 

while ((dataRead = networkStream.Read(buffer, 0, buffer.Length)) > 0) 
{ 
    List<byte> actualBuffer = (new List<byte>(buffer)).GetRange(0, dataRead); 

    string data = System.Text.Encoding.UTF8.GetString(actualBuffer.ToArray()); 
    Console.WriteLine("Raw data: {0}", data)); 
    mainBuffer += data; 
    Console.WriteLine(mainBuffer); 
} 

あなたがStringBuilder代わりのstringを使用することを検討すべきであることをここで言及する怒っています。

関連する問題