c# - C#多线程服务器-通用客户端集合可能是一个问题

标签 c# multithreading list sockets

我正在使用异步套接字在C#中开发游戏e。当前,该程序使用列表来存储客户端。

如果客户端加入 session 室,则会创建一个本地列表,该列表存储该特定 session 室中的所有用户(我正在使用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的客户端 volatile bool 值更改为false(用于在执行套接字操作之前检查用户是否仍处于连接状态)例如BeginSend等)。如果某个客户从X session 室断开连接而其他一些客户加入X session 室怎么办?当然,它仍然会在本地列表中,但是ConnectionFired bool会更改其值吗?我猜不是。它仅影响主/原始列表。

我担心的是,如果发生这种情况,那么服务器可以尝试将数据发送到封闭的套接字(因为检查此问题的 bool 值ConnectionFire在需要时不会更改其值)。

为避免这种情况,我应该避免对列表进行克隆,而直接在主列表中将用作吗? (我最初做了这个locallist的事情是为了避免集合被修改的异常)。

最佳答案

你似乎在这里问两个问题

  • 您担心以线程安全的方式管理集合
  • 您担心在对方断开连接时尝试通过套接字发送数据。

  • 在信息有限的情况下回答您的问题
  • 如果您有多个线程在访问列表,则需要一个线程安全的实现。您可以使用锁等自己滚动,也可以使用新的.NET之一。
    http://msdn.microsoft.com/en-us/library/dd997305.aspx
    关于您对“本地”列表的评论,简单的答案是不制作本地副本,除非您要冒拥有过时数据的风险。使用线程安全列表,并直接对其进行枚举。如果使用LINQ表达式,则可以进行复杂的查询,而无需制作集合的任何副本。
  • 通过套接字发送数据时,您总是需要处理另一方离开的情况。如果它们消失了,那么您必须处理错误并决定是要重试还是继续执行下一个任务。您根本无法预先预测另一方何时会死亡或它是否会以优美的方式告诉您(例如“再见”)。因此,在一个非常简单的解决方案中,将您的sendPacket包装在一些异常(exception)处理/日志记录中。
  • 关于c# - C#多线程服务器-通用客户端集合可能是一个问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18723229/

    相关文章:

    c# - 无法将服务引用添加到 OData 端点

    wpf - 如何将方法调用委托(delegate)给另一个线程?

    java - Apache Camel 中 Seda 的并发消费者

    c# - 带有匈牙利 CultureInfo 的 String.Compare() 对于特定字符串不正确

    c# - 关于 C# 短路评估的最佳实践是什么?

    html - 垂直滚动捕捉部分内的水平滚动捕捉部分,由于 ul 和 div 的原因,上方有空白空间

    python - 循环遍历字符串项列表并返回那些包含 python 子字符串的项

    python - 如何在 python 中过滤列表字典?

    C# - 如果要插入到 mysql 的值已经存在,如何通知用户

    C++无锁线程同步