2011-08-11 7 views
0

今は完全に混乱しています。.NET Async Serverは明白な理由でデータを受信して​​いません

編集:よろしくお願いします。 Pythonソケットも今やっています。

編集2:これは高いCPU使用率を引き起こしているのかどうかは分かりませんが、ランダムなものがあります。使用法のスパイクを引き起こす原因を突き止める効率的な方法はありますか?このプロジェクトは少し大きく、さまざまなスレッドがあります。

私は、受信した接続を待ち受けて待機している非同期サーバーを持っていて、それらを有効に保ち、ソケットがフラッシュしてサーバーデータを与えるのを待ちます。ユーザーがソケットを閉じたい場合にのみ閉じます。

しかし、私がソケット&ストリームを接続したままにしておくと、それはひそかになり始め、無限ループで空のデータを送信し始めます... 15秒から1分以上かかることがあります。私がのために実際にの時間を過ごすと、それは本当に高いCPU使用率を引き起こします。

高いCPU使用率を除けば、奇妙なことに、すべてが正常に動作します。メッセージは&で届きました。

これは私の読み取りコールバック関数です:

protected void ReadCallback(IAsyncResult ar) 
    { 
     StateObject state = (StateObject)ar.AsyncState; 
     Socket handler = state.SocketHandle; 

     try 
     { 
      int bytesRead = (state.BytesRead += handler.EndReceive(ar)), offset = 0; 
      string line = m_Encoder.GetString(state.Buffer, 0, bytesRead); 
      if (state.Buddy != null) 
       Console.WriteLine(state.Buddy.Address); 
      if (bytesRead > 0) 
      { 
       Console.WriteLine("!!!"); 
       /* A complete request? */ 
       if (line.EndsWith("\n") || line.EndsWith("\x00")) 
       { 
        string[] lines = line.Split('\n'); // ... *facepalm* 
        foreach (string ln in lines) 
         this.MessageReceieved(ln, state); 

        state.Buffer = new byte[StateObject.BUFFER_SIZE]; 
        state.BytesRead = 0; // reset 
       } 
       /* Incomplete; resize the array to accommodate more data... */ 
       else 
       { 
        offset = bytesRead; 
        Array.Resize<byte>(ref state.Buffer, bytesRead + StateObject.BUFFER_SIZE); 
       } 
      } 
      if (handler != null && handler.Connected) 
       handler.BeginReceive(state.Buffer, offset, state.Buffer.Length - offset, SocketFlags.None, new AsyncCallback(ReadCallback), state); 

     } 
     catch (SocketException) 
     { 
      if (state.Buddy != null) 
       state.Buddy.Kill(); 
      else 
       handler.Close(); 
     } 
    } 

私はこれは何とかBeginReceiveを呼び出すことによって引き起こされるけど、私は生きて接続を維持するためにどのように他を知りません。

答えて

2

このコードには何かがありません。

しかし、私はいくつかの問題を参照してください。

接続検出

ソケットが接続されているかどうかを確認する必要はありません。あなたは、受信コールバックの2通りの方法で切断を検出することができます:

  1. ゼロバイトは例外がスローされEndReceive
  2. によって返されます。

EndReceiveの後に最初に行うことは、戻り値をチェックし、それに応じて切断することです。それはコードを明確にします。

0バイトを受信すると、コードは現在何も行いません。 handlerは受信を停止し、接続がまだ開いていると考えます。

バッファ取り扱い

あなたのバッファの扱いは非常にinneffecientです。毎回バッファのサイズを変更しないでください。それはあなたのサーバーを大幅にダウンさせるでしょう。最初から大きなバッファを割り当てます。

を扱う

文字列にあなたが何かを受け取るたびにビルドしないでください。新しい行またはnullの後にバイトバッファの内部をチェックしてください。それから文字列を作成し、必要なだけ大きくします。あなただけのメッセージ(例えば、1つのメッセージと半分のメッセージ)より多くのバイトを受け取るかもしれません。

+0

ありがとう!私はちょうどゼロバイトが読み込まれているかどうかを確認するためにelseを追加した後、接続が終了していない場合は接続を閉じます。これは問題を解決したようです(今のatleast)! –

関連する問題