次の要件を満たすためのベスト プラクティスを探しています。
- 複数のクライアント ソケットを非同期で処理するフレームワーク
- 各着信メッセージ プロトコルは、各メッセージがフォーマット文字列であり、改行文字 '\n' で完全にマークされていることを指示します。
- クライアント側は完全に制御できますが、サーバー側は制御できません。サーバーは、メッセージの完了を示す改行文字を含む文字列ベースのメッセージを受け入れて送信します。
- 接続された各ソケットを介していつでもメッセージを送信できるようにしたい (各ソケットはメッセージを送受信できる)。
- 着信メッセージは、コールバックを介して転送する必要があります。
- 接続されたすべてのソケットからのすべての受信完了メッセージを 1 つのコールバックにルーティングするか、各ソケット クライアントが独自のコールバックを実装するかを実装で選択できるようにしたいと考えています。
- 最大 4 つのクライアント/ソケットで接続します。そのため、このような限られた数のソケットを活用し、それらすべてを同時に管理できる提案を探しています。
私が使用BeginReceive
しEndReceive
、実装された IAsyncResult コールバックを使用するフレームワークが、.Net 4.5 をターゲットにしていることを考えると、最先端のものであるかどうか疑問に思います。NetworkStream や他の API の選択肢を使用するなど、より良い解決策はありますか? BeginReceive/EndReceive の実装で本当に困っているのは、EndReceive の後で、BeginReceive を再度呼び出して、コールバックを再度登録する必要があることです。それは私にとってはひどい量のオーバーヘッドのように聞こえます。新しいデータをいつでも非同期に追加できず、同時に別のコンテキストが完全なメッセージを構築し、発生したイベントを介してルーティングできないのはなぜですか?
IAsyncResult を使用する理由は、多くの場合、スレッド処理が処理されるという点で行われますが、次のことに反対するものがあります: NetworkStream を使用し、ストリームから読み書きするだけです。前述のように、文字列メッセージのみが交換され、プロトコルごとの各メッセージは改行文字によって完全にマークされます。別のタスク/スレッドは、 を介して (ネットワーク ストリームに基づいて) ストリームリーダーをポーリングしますReadLine()
。これ以上簡単なことはないでしょう?
私が基本的に求めているのは、次のコードを真に非同期にするにはどうすればよいかということです。
public class SocketClient
{
private TcpClient client;
private StreamReader reader;
private StreamWriter writer;
public event Action<string> MessageCallback;
public SocketClient(string hostname, int port)
{
client = new TcpClient(hostname, port);
try
{
Stream stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.AutoFlush = true;
//Start Listener on port
StartListener();
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
}
public void StartListener()
{
Task task = Task.Factory.StartNew(() =>
{
while (true)
{
if (MessageCallback != null)
{
MessageCallback(reader.ReadLine());
}
//Thread.Sleep(200);
}
});
}
}