2010-10-21 144 views
1

您好我正在编写多线程客户端服务器的任务。 到目前为止,我所做的是在一个端口中打开一个套接字,并分叉两个线程以便倾听和写入客户端。但我需要将两种类型的客户端连接到服务器并以不同的方式提供服务。我的问题是什么将是我最好的方法?多线程客户端服务器

我正在处理具有无限循环接受连接的类中的连接。当连接被接受时,这个类创建两个线程来读写客户端?现在,如果我想处理另一种不同类型的客户,我们应该怎么做?

我需要打开另一个端口吗?还是有可能通过同一个端口服务?可能是,如果可以识别套接字中的客户端类型比我可以以不同的方式处理消息。

或者你是否建议这样吗?

  1. 为两种类型的客户端分叉两个线程,并监视不同端口中每个线程中的入站连接。
  2. 当一个连接接受每个线程产生另外两个线程进行监听和写入。

请提出建议。

回答

0

不同的协议通常在不同的端口上提供服务。但是,您可以通过协商要使用的协议,通过同一端口为两种类型的客户端提供服务。这可以像客户发送HELOEHLO一样简单来请求一种或另一种服务。

4

也许你会从Unix用户得到更好的答案,但我会提供我所知道的。

您的服务器需要一个线程来打开等待传入连接的“侦听”套接字。这个线程可以作为简单的主线程,但是如果你关心UI交互的话,它可以是一个备用线程(例如在Windows中,这是一个担心,对Unix没有把握)。这听起来像你至少这么远。

当“侦听”套接字接受连接时,您会看到一个连接到“客户端”套接字的“连接”套接字。您可以将此“连接”套接字传递给一个新线程,该线程管理从写入“连接”套接字的读数。因此,我建议的一个改变是在一个线程中管理'连接'套接字,而不是像你所做的那样在两个单独的线程中(一个用于读取,一个用于写入)。使用select()系统调用可以完成对相同套接字的读写操作,如here所示。

当新的客户端连接时,您的'侦听'套接字将提供一个新的'连接'套接字,您将切换到另一个线程。此时,您有两个线程 - 一个管理第一个连接,一个管理第二个连接。就套接字而言,客户之间没有区别。你只需要两个开放的连接,一个连接到你的两个客户端。

在这一点上,问题变成了“为他们提供不同的服务”意味着什么。如果客户希望以独特的方式与服务器交互,那么必须以某种方式确定。交互可以根据您可以查询的'客户端'套接字的IP地址来确定,但这似乎是任意的,并且会受到网络更改的影响。它也可以基于从'客户'套接字接收到的指示所需交互类型的初始数据块。在这种情况下,管理'连接'套接字的线程可以读取预期类型交互的套接字,然后将套接字交给管理该交互类型的类对象。

我希望这会有所帮助。

1

您可以在一个线程中处理单个客户端连接上的读写操作。基于多线程的最简单的解决方案将是这样的:

// C++ like pseudo-code 
while (server_running) 
{ 
    client = server.accept(); 
    ClientHandlingThread* cth = CreateNewClientHandlingThread(client); 
    cth->start(); 
} 

class ClientHandlingThread 
{ 
    void start() 
    { 
     std::string header = client->read_protocol_header(); 
     // We get a specific implementation of the ProtocolHandler abstract class 
     // from a factory, which create objects by inspecting some protocol header info. 
     ProtocolHandler* handler = ProtocolHandlerFactory.create(header);   
     if (handler) 
      handler->read_write(client); 
     else 
      log("unknown protocol") 
    }  
}; 

为了扩展更好,你可以使用一个线程池,而不是产生一个新的线程为每个客户。有许多free thread pool实现for C++

while (server_running) 
{ 
    client = server.accept(); 
    thread_pool->submit(client); 
    cth->start(); 
} 

服务器可以通过使用一些实现reactor pattern的框架进一步改进。他们在引擎盖下使用selectpoll功能。您可以直接使用这些功能。但对于生产系统来说,最好使用现有的反应器框架。 ACE是用于开发高度可扩展的并发应用程序的最广为人知的C++工具包之一。