2012-10-23 25 views
21

我正在实现一个简单的服务器,它接受单个连接,然后使用该套接字同时读取和写入来自读写线程的消息。 什么是安全和简单的方式来同时读取和写入在Linux上的c/c + +的相同套接字描述符? 我不需要担心多个线程从同一个套接字读取和写入,因为将有一个专用读取和单个专用写入线程写入套接字。同时在C或C++的相同套接字上读写

在上述情况下,是否需要任何类型的锁定?

上述场景是否需要非阻塞套接字?

是否有任何开源库,这将有助于上述情况?

回答

24

在上述情况下,是任何一种锁定需要的?

无。

是否出现上述情况需要非阻塞插座?

您可能担心的一点 - 已建立连接上的读写线程 - 如果您对那些线程坐在那里等待完成感到高兴,则无需非阻塞。这通常是您使用线程而不是选择或轮询或异步操作的原因之一,也使代码更简单。

如果线程接受新的客户很高兴在调用块来accept(),那么你所有的好也有。

不过,有一个与你可能要保持在你的脑海里TCP服务器的一个微妙的问题......如果你的程序的增长来处理多个客户端,并具有一定的周期性的看家做。使用带有超时的select语句来检查监听套接字的可读性 - 这表明客户端连接尝试 - 然后连接accept是自然而诱人的。有一个竞争条件有:客户端连接尝试可能select()accept()之间下降,在这种情况下,如果监听套接字不是非阻塞accept()将阻止,并能防止及时归还到select()环和停止定期导通超时处理直到另一个客户连接。

是否有任何开源库,这将有助于上述情况?

有数百个用于编写基本服务器的库,但最终你所要求的是在操作系统提供的BSD套接字或其Windows混蛋上轻松实现的。

+3

+1提到的竞争条件和设计选项使用线程vs选择或轮询 – Jimm

+1

@Tony D好建议。从增强的角度来看,如果将来他计划使用OpenSSL,那么他的架构可能会改变。他不能在同一个SSL *上同时读写。 – enthusiasticgeek

+0

@enthusiasticgeek:有趣 - 我没有做SSL编程,所以不知道这一点,但绝对值得记住。干杯。 –

11

您不必担心。一个线程读取和一个线程写入将按照您的预期工作。套接字是全双工的,因此您可以在写入时阅读,反之亦然。如果你有多个作家,你不必担心,但情况并非如此。

12

插座是双向的。如果您实际上已经剖析了以太网或串行电缆,或者看到了它们的低级硬件布线图,则实际上可以为“TX”(发送)和“RX”(接收)线路查看不同的铜线。从设备控制器发送信号的软件到用于'套接字'的大多数OS API都反映了这一点,这是大多数系统(例如Linux)上的套接字和普通管道之间的主要区别。

要真正获得最大的插座,您需要:
1)使用IO完成端口,epoll的(),或一些类似的异步回调或事件系统“唤醒”,每当数据来自异步IO支持在插座上。然后,这必须调用最低级别的ReadData API来从套接字连接中读取消息。
2)支持低级写入的第二个API,一个'WriteData'(发送),将字节推送到套接字上,并且不依赖于'ReadData'逻辑需要的任何内容。请记住,即使在硬件级别,您的发送和接收也是独立的,因此不要在此级别引入锁定或其他同步。
3)Socket IO线程池,它盲目地处理从套接字读取或写入套接字的数据。
4)PROTOCOL CALLBACK:套接字线程具有智能指针的回调对象。它处理任何PROTOCOL层 - 例如将数据blob解析为真正的HTTP请求 - 位于基本套接字连接之上。请记住,套接字只是计算机之间的数据管道,通过它发送的数据通常会以一系列碎片的形式到达数据包。在像UDP这样的协议中,数据包甚至不是​​按顺序排列的。低级别的“ReadData”和“WriteData”将从它们的线程回调到这里,因为它是内容感知数据处理实际开始的地方。
5)协议处理程序本身需要的任何回调函数。对于HTTP,您将原始请求缓冲区打包为很好的对象,然后交给一个真正的servlet,该servlet应该返回一个很好的响应对象,该响应对象可以序列化为符合HTTP规范的响应。

注意基本模式:如果您希望充分利用套接字上的双向异步IO,则必须使整个系统从根本上异步(“回调的洋葱”)。同时读取和写入套接字的唯一方法是使用线程,因此您仍然可以在“编写器”和“读取器”线程之间进行同步,但是只有在协议或其他考虑事项强迫我时才会执行该操作。好消息是,使用高度异步处理的套接字可以获得很好的性能,但糟糕的是,以强大的方式构建这样一个系统是一项严肃的工作。

+4

'双向'是不够的。半双工仍然是双向的,但不是同时。它需要全双工来满足OP的要求。 TCP/IP是全双工的,也是双向的。 – EJP