2010-07-13 18 views
4

我编码插槽服务器,该服务器是对我的球技,我使用非阻塞的套接字和大约10个线程,从不同的插座同时接收数据(第一线从0-100接收,第二从101-200等..)C++套接字发送()线程安全的1000个客户最高要求

但如果线程1想要将数据发送到所有1000个客户端和线程2还希望在同一时间将数据发送给所有的1000个客户端,那是安全的吗?数据在其他(客户端)方面是否存在混淆的可能性?

,如果是,我想可能发生的唯一的问题是,有时客户会收到2个或10个数据包为一包,是正确的?如果是的话,有没有解决这一:(

+0

同意ckv提供的答案,但我会建议重新考虑这种方法。有10个线程可以从不同的时间间隔读取不同套接字的好处?让线程从您的架构中的套接字和异步处理组件中读取可能会更容易。 – 2010-07-13 08:59:47

+0

@Daniel我想你是指每个套接字都有一个线程。对? – ckv 2010-07-13 09:21:16

+1

当其中一个正在阅读时,大多数线程将等待。使用'select()'这样的东西可能是一个更好的选择,并且可以降低复杂性。事实上,它甚至可能会更快。 – ereOn 2010-07-13 09:26:48

回答

2

处理很多插座通常的模式是有I/O活动专用线程轮询select(2)poll(2),或更好kqueue(2)epoll(4)(取决于平台)作为插座事件调度。套接字通常以非阻塞模式处理。然后,可能会有线程池对事件作出反应,并且可以直接读取或写入,也可以通过较低级别的缓冲区/队列进行读取和写入。

各种技术适用于此 - 从排队到事件订阅白板。在I/O级别上多路复用接受/读取/写入/ EOF以及在应用程序级别上进行事件仲裁会变得棘手。像libeventboost::asio这样的几个库帮助构建较低层(ACE库也在这个空间中,但我讨厌将其推荐给任何人)。你将不得不自己拿出应用程序级协议和状态机(再次boost::statechart可能会有所帮助)。

一些很好的链接来获得你反对什么更好的了解(这可能是他们在这里提到的SO百万次):

道歉因为没有提供具体的解决方案,但这是一个非常广泛的设计问题,大多数决策都很大程度上依赖于上下文(虽然很有趣)。希望这个对你有帮助。

+0

TNX,这有助于很多 – Tenev 2010-09-28 15:32:14

1

由于使用不同的插座发送数据时,必须不存在任何问题。而当这些不同的线程访问相同的数据,你必须确保数据的完整性。

+0

不是真的,每个线程都可以在不同的套接字上接收数据,但它可以将数据发送到所有套接字.. – Tenev 2010-07-13 09:06:11

+1

对不起,但我没有理解您的评论。你可以更清楚一点,或者你可以编辑你的问题,以便更清楚。 – ckv 2010-07-13 09:12:08

+0

线程可以发送到所有套接字,但可以从某些套接字接收 – Tenev 2010-07-13 09:43:13

-1

的send()是不是在大多数实现原子,所以发送给从多个线程1000个不同的插座会导致到达客户端上的混合式消息,以及各种古怪的。 (我什么都不知道,看Nicolai的和罗伯特的我的评论下面的评论仍然存在(就解决您的问题而言))

我会做的是使用线程发送像你使用它们接收。一个线程来管理发送到一个(或多个)套接字,以确保您不会同时从多个线程写入一个套接字。

也期待here一些额外的讨论和更有趣的链接。 如果你使用的是windows,那么winsock programmers faq是一个非常宝贵的资源,你的问题见here

+0

嗯我在想这个,我会这样做,如果我知道如何,即时通讯使用fd_set的接收与选择(),但我不知道如何触发事件fd_set的如果我使用select()进行写入/发送 – Tenev 2010-07-13 09:53:30

+1

您确定吗? 'send(2)'是一个系统调用 - 它必须是**原子**。尽管关于每个“send(2)”实际消耗的字节数,线程安全性是一个不同的问题。 – 2010-07-14 04:24:32

+0

@tenev,看看** libevent **:http://monkey.org/~provos/libevent/ - 使编码协议状态机变得更加容易。 – 2010-07-14 04:26:17

0

您使用的是UDP还是TCP套接字?

如果是UDP,每个写入都应封装在一个单独的数据包中,并且应该完整地传送到另一侧。订单可以交换(因为它可能用于任何UDP数据包),但它们应该是完整的。

如果TCP,有没有在传输层上的数据包的概念和在一侧上的任何10个写入可能在一个读取被捆绑起来在另一侧上。 TCP写入也可能只接受缓冲区的一部分,所以即使send()函数是原子的,你的写入也不一定。在这种情况下,你需要同步它。

+0

TCP,同步...我必须设置非阻塞或阻塞套接字?如果它们是非阻塞的,我认为我不能同步它们,因为在SEND()之前使用Select(),我正在使用pthread_rwlock_wrlock(&players [socket] .islocked);选择SEND后(玩家[socket] .socket)终于解锁(&players [socket] .islocked)是一个很好的解决方案^^?看起来像对我来说最快的一个 – Tenev 2010-07-14 17:53:34

+0

与同步我的意思是你必须手动将字节流分成数据包。无论您如何发送它,您的客户端都会收到一个字节流(异步/非阻塞无关紧要)。尝试短时间连续写入5个字节10次 - 另一侧最有可能收到50个字节的数据块。 TCP是一个字节流。如果你想要的数据包,你将不得不使他们。 – dascandy 2010-07-19 22:08:11

相关问题