Java多线程有状态服务器-网络设计

4

我正在尝试实现一个有状态的、多客户端服务器应用程序,并对网络/线程设计有一些疑问。我目前面临的问题是如何在通信层和逻辑层之间交换消息。

服务器处理多个客户端,每个客户端可以在多个“通道”中活动,每个通道都有多个阶段,可能有多个客户端在其中操作。类比于具有多个房间的聊天程序。

我已经实现了服务器端消息的接收。每个客户端都有自己的线程,阻塞式读取数据并解码成消息。现在该怎么办?在我的观点中,每个通道也应该有自己的线程来轻松地维护其状态。我可以使用BlockingQueue来交换接收到的消息和通道线程,后者在该队列上阻塞式等待新消息。

但是如何向客户端发送消息呢?通道中的逻辑将处理消息,并产生要发送给一个/一些/所有客户端的消息。是否安全直接使用通道线程直接写入套接字?还是应该使用另一个BlockingQueue将消息传输到客户端处理程序线程?但是如何唤醒它,因为它正在套接字上等待读取?或者是否应该为每个客户端使用单独的发送线程,甚至单独的发送套接字?

顺便说一句:我知道可以使用现有的网络层库,但我想从头开始使用普通套接字实现它。


我不确定如果处理廉价且每个消息的话,是否应该使用多线程,我会考虑使用反应器。每个客户端和/或通道都有状态并不意味着必须使用线程。 - sinelaw
@sinelaw 我猜你指的是NIO。我读了这篇文章http://paultyma.blogspot.com/2008/03/writing-java-multithreaded-servers.html,比较了NIO/IO,所以我选择使用一线程每连接(已经实现)。但对于通道,可以选择另一种方法...然而,实际问题将是相同的。 - king_nak
2个回答

1
在包装套接字的通信对象上放置一个发送消息方法。同步此方法,以便一次只能有一个线程调用它。然后,无论多少个线程调用此方法都没有关系。每条消息将仅一次发送。您也不必打扰正在阻塞读取的线程。这个发送方法将是足够快的操作,您不必担心其他线程在线程发送时阻塞。
只要通道对于每个连接的客户端都有通信对象的引用,它就可以发送消息而不必担心。
如果它曾经引起问题,您总是可以修改该发送消息以将要发送的对象排队。然后,您可以有一个特定的发送线程在队列上阻塞并将内容写入套接字。但根据我的经验,这是不必要的。

这就是我所说的“直接写入套接字”的意思,这是一个糟糕的表述。但对我来说,为“读取传入消息”和“处理消息并向多个客户端编写响应”分别创建一个线程似乎很奇怪。但也许这只是我对线程任务解耦的偏好... - king_nak
你的通道线程不是应该处理多个通信对象的消息并写入响应吗?我不明白为什么在该线程和通信对象之间需要任何其他东西。实际上,该线程将通过通信对象直接向所有套接字进行写入。 - Erick Robertson

-1

那事件机制怎么样?当您完成处理请求并有客户端可用的数据时,只需使用客户端套接字处理线程发送事件即可。因为来自客户端的传输已结束,所以可以正常发送回复 - 如果我想得正确的话。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接