我们创建的其中一个工具也遇到了类似的情况(我没有直接使用它,但解决方案似乎运行良好)。每次我们收到客户时,我们都会将相关信息存储在一个类中(类似于示例中的 StateObject 类)并将该类添加到 ArrayList 中(效果很好),但我认为更好的解决方案是将类存储在 Dictionary :
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
Dictionary 类允许您将 Key 映射到对象。这使您可以使用唯一键轻松访问对象。因此,在接收到新客户端时,您可以按照您希望的方式为该客户端创建一个 ID(这可能只是一个整数,每次客户端连接时都会递增),创建一个状态对象类并将您需要的相关信息存储在该类中,然后将 Key Class 对添加到字典中,类似于:
// Global definition of Client dictionary
// The first argument within <> is the key type, the second argument
// is the type of object that key will map to
Dictionary<int, StateObject> Clients = new Dictionary<int, StateObject>();
// Accept client callback
public static void AcceptCallback(IAsyncResult ar)
{
// Get the socket that handles the client request.
Socket listener = (Socket) ar.AsyncState;
Socket handler = listener.EndAccept(ar);
StateObject client = new StateObject();
// Then set all the variables of client here
Clients.Add(ID, client);
}
注意:但是,您要创建自己的 ID,它们对于字典中的每个条目都必须是唯一的。
我的建议是将每个接受的套接字客户端的处理程序存储在 StateObject 中。这样,您始终可以访问可以向每个连接的客户端发送信息的句柄(这就是我们使用 Tcp 连接的方式,我们将 TcpClient 及其底层 Stream 存储在 StateObject 类中,然后通过这些与每个客户端进行通信变量。我假设这也可以通过 Sockets 实现?)
现在存储所有信息后,您可以使用字典中的 ID 键来识别要与哪些客户端进行通信。使用 LINQ 为您提供了一个不错的单行选择命令:
// Selects state objects from Clients dictionary where ID has a value greater than 5
IEnumerable<StateObject> Clients.Where(c => c.Key > 5).Select(c => c.Value);
(我认为这是有效的 LINQ 查询,但需要检查,它本质上是说从客户端列表中选择每个 StateObject,其中 ID 大于 5)
如果您不希望 ID 以这种方式识别客户端,您可以遍历字典中的每个 StateObject 并检查内部变量以查看您是否向客户端发送消息。比如:
foreach (StateObject client in Clients.Values)
{
if (client.ImportantVariable == true)
// Send client information via socket here
}
由您决定哪种方法最适合您的需求。希望这对您有所帮助,并且是一个可行的解决方案。