0

私はソケットプログラミングに少し苦労しています(私はまったく慣れていないものです)。GoogleやMSDNから役立つものは何も見つかりません(ひどい)。これの長さについてお詫び申し上げます。

基本的に、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: これでいいのかどうかわかりません。リモート サービスからのデータは、どのようにして適切なリッスン スレッドに到達するのでしょうか? リクエストごとにソケットを作成する必要がありますか?

ここの私の快適ゾーンの外。助けが必要。

4

4 に答える 4

0

送信したメッセージに対する応答を確実に受け取ることを知っていますか?ソケットから非同期動作を削除し、同期的に送受信を試みます(これにより、今のところスレッドがブロックされる可能性があります)。この動作が機能していることがわかったら、質問を編集してそのコードを投稿してください。スレッドモデルのサポートを行います。ネットワーク部分、つまり送信/受信が機能すると、スレッドモデルは非常に簡単になります。

于 2009-05-15T15:38:31.757 に答える
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;
}

病気は助けてみてください!2番目のコード投稿は、私たちが作業できるものであり、今後の方向性です。

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

于 2009-05-15T15:28:29.970 に答える
0

考えられる問題の 1 つは、送信操作がサーバーに送信され、Windows が非同期リスナーを設定する前にサーバーが応答する場合です。リッスンしていない場合、データはあなたの側で受け入れられません (TCP とは異なります) 送信操作の前に beginread を呼び出してみてください。

于 2010-04-07T23:37:07.810 に答える