私はソケットプログラミングに少し苦労しています(私はまったく慣れていないものです)。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: これでいいのかどうかわかりません。リモート サービスからのデータは、どのようにして適切なリッスン スレッドに到達するのでしょうか? リクエストごとにソケットを作成する必要がありますか?
ここの私の快適ゾーンの外。助けが必要。