1

非同期ソケットを使用して c# でゲーム エミューを開発しています。現在、プログラムは List を使用してクライアントを格納しています。

クライアントがルームに参加すると、その特定のルームのすべてのユーザーを格納するローカル リストが作成されます (FindAll(x => x.room == this.room) を使用しています)。クライアントがルームを変更すると、クライアントが参加したルーム内の他のすべてのプレーヤーを通知するためにサーバーが特定のパケットを送信する必要があるため、このリストが必要です。

このようなもの:

var localist = Clients.FindAll(x=> x.room == this.room);
foreach(stateObj client_in_room in locallist)
{
    client_in_room.sendPacket(...); //what if the client_in_room disconnected in the meanwhile?
}

クライアントが切断されると、そのクライアント (stateObj) が元のクライアント リストから削除され (そしてクライアント ソケットが閉じられ)、ConnectionFired と呼ばれるクライアントの揮発性ブール値が false に変更されます (ソケット操作を実行する前に、ユーザーがまだ接続されているかどうかを確認するためのものです)。 BeginSend など)。ルーム X に他のクライアントが参加しているときに、あるクライアントがルーム X から切断された場合はどうなりますか? 確かにローカルリストには残りますが、ConnectionFired bool はその値を変更しますか? そうではないと思います。メイン/元のリストにのみ影響します。

私の懸念は、それが発生した場合、サーバーが閉じたソケットにデータを送信しようとする可能性があることです (これをチェックする bool、ConnectionFire は、必要に応じてその値を変更しないため)。

このようなことを避けるには、リストの複製を避け、メイン リストで直接forを使用する必要がありますか? (コレクションが変更された例外を回避するために、最初にこのローカルリストのことを行いました)。

4

1 に答える 1

1

Yuo ここで 2 つの質問をしているようです

  1. スレッド セーフな方法でコレクションを管理することに関心がある

  2. 相手が切断されているときにソケットを介してデータを送信しようとすることに懸念があります。

情報が限られていることから、お客様の懸念にお答えするために

  1. リストにアクセスするスレッドが複数ある場合は、スレッドセーフな実装が必要です。lock などを使用して自分でロールするか、新しい .NET のいずれかを使用できます。 http://msdn.microsoft.com/en-us/library/dd997305.aspx 「ローカル」リストについてのコメントについては、単純な答えは、古いデータを持つリスクを冒したくない限り、ローカル コピーを作成しないことです。スレッド セーフ リストを使用し、それを直接列挙します。LINQ 式を使用すると、コレクションのコピーを作成する必要なく、複雑なクエリを作成できます。

  2. ソケットを介してデータを送信する場合、相手が去ったときに常にケースを処理する必要があります。それらがなくなった場合は、エラーを処理して、再試行するか、次のタスクに進むかを決定する必要があります。別のパーティーがいつ死ぬか、またはそれが優雅な方法であなたに告げるかどうか(たとえば、「さようなら」)を事前に予測することはできません。したがって、非常に単純なソリューションでは、 sendPacket を例外処理/ロギングでラップします。

于 2013-09-10T16:14:52.903 に答える