2009-05-15 25 views
0

私はソケットプログラミング(私が慣れていないこと)に苦労しています.GoogleやMSDN(ひどい)から助けてくれるものは何も見つかりません。これについての謝罪非同期UDPソケットの問題

私は基本的にUDPを介して要求を受信して​​応答する既存のサービスを持っています。私はこれを全く変えることはできません。

また、Webapp内にそのサービスへの応答をディスパッチしてリッスンするクライアントもあります。私は与えられた既存のクライアントは、ソケットと応答スロットの配列を作成し、 "sock.Receive()"呼び出しを受信し、受け取ったデータをプッシュする無限ループメソッドを持つバックグラウンドスレッドを作成するシングルトンですスロットアレイ。これに関するすべての種類のことが私には間違っているように見え、無限のスレッドはユニットテストを中断させます。このサービスを、代わりに非同期的に送受信するように置き換えようとしています。

ポイント1:これは正しいアプローチですか?私は非ブロッキング、スケーラブル、スレッドセーフなサービスが欲しいです。

私の最初の試みは大雑把にはうまくいきましたが、取り返しのあるデータは常に予想よりも短かったです(つまり、バッファには要求されたバイト数がありませんでした)。

private Socket MyPreConfiguredSocket; 

public object Query() 
{ 
    //build a request 

    this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target); 

    IAsyncResult h = this._sock.BeginReceiveFrom(response, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), this._sock); 

    if (!h.AsyncWaitHandle.WaitOne(TIMEOUT)) { throw new Exception("Timed out"); } 

    //process response data (always shortened) 
} 

private void ARecieve (IAsyncResult result) 
{ 
    int bytesreceived = (result as Socket).EndReceiveFrom(result, ref this._target); 
} 

私の2番目の試みは、私が頻繁に見たより多くのGoogleトローリングとこの再帰パターンに基づいていますが、このバージョンは常にタイムアウトします。それは決してはARecieveになる。

public object Query() 
{ 
    //build a request 

    this.MyPreConfiguredSocket.SendTo(MYREQUEST, packet.Length, SocketFlags.Multicast, this._target); 

    State s = new State(this.MyPreConfiguredSocket); 

    this.MyPreConfiguredSocket.BeginReceiveFrom(s.Buffer, 0, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s); 

    if (!s.Flag.WaitOne(10000)) { throw new Exception("Timed out"); } //always thrown 

    //process response data 
} 

private void ARecieve (IAsyncResult result) 
{ 
    //never gets here! 
    State s = (result as State); 
    int bytesreceived = s.Sock.EndReceiveFrom(result, ref this._target); 

    if (bytesreceived > 0) 
    { 
     s.Received += bytesreceived; 

     this._sock.BeginReceiveFrom(s.Buffer, s.Received, BUFFER_SIZE, SocketFlags.None, ref this._target, new AsyncCallback(ARecieve), s); 
    } 
    else 
    { 
     s.Flag.Set(); 
    } 
} 

private class State 
{ 
    public State(Socket sock) 
    { 
     this._sock = sock; 
     this._buffer = new byte[BUFFER_SIZE]; 
     this._buffer.Initialize(); 
    } 

    public Socket Sock;  
    public byte[] Buffer;  
    public ManualResetEvent Flag = new ManualResetEvent(false); 
    public int Received = 0; 
} 

ポイント2:明らかに私はかなり間違っています。

ポイント3:私はこの権利について行くのか分かりません。リモートサービスからのデータは、どのように正しいリスニングスレッドに到達しますか?リクエストごとにソケットを作成する必要がありますか?

ここから私の快適ゾーン外です。助けが必要。

+0

あなたはUDTライブラリを知っていますか? CSHARPで – lsalamon

+0

または[RUDP](http://rudp.codeplex.com/)を試してください – lsalamon

答えて

0

あなたのための解決策ではなく、単なる提案 - すべてのスレッド/イベント/などをはがす最も簡単なコードを考え出してください。そこから、必要性が増し始め、必要なだけ複雑になります。私の経験はいつも私が間違っていたことを見つけ出す過程であった。

+0

問題は、これは私がこれまでどのようになっているかです:) –

0

あなたのプログラムSUDOの概要は次のとおりですか?

Socket MySocket; 
Socket ResponceSocket; 

byte[] Request; 
byte[] Responce; 

public byte[] GetUDPResponce() 
{ 
    this.MySocket.Send(Request).To(ResponceSocket); 

    this.MySocket.Receive(Responce).From(ResponceSocket); 

    return Responce; 
} 

ill tr​​y help! 2番目のコードポストは、私たちが協力して進める方法です。

しかし、あなたは正しいです!ドキュメントは最高ではありません。

0

送信したメッセージに確実に応答することがわかりますか?ソケットから非同期の振る舞いを取り除き、同期的に送受信しようとしてください。この動作が動作していることがわかったら、質問を編集してそのコードを投稿してください。スレッドモデルについてお手伝いします。ネットワーク部分、すなわち送信/受信が機能していると、スレッドモデルはかなり簡単です。

0

問題は、送信操作がサーバーに送信され、ウィンドウが非同期リスナーを設定する前に応答する可能性があります。あなたがデータを聞いていないなら、あなたの側では受け入れられないでしょう(TCPと違って) send操作の前にbeginreadを呼び出してみてください。