我在一次面试中被问到这个问题,我的回答是避免使用多个线程,使用“协作多任务处理”(单进程)。我非常想知道如何在C++跨平台服务器中有效地处理多个客户机,而不必为每个客户端设置线程。C++11是否提供了一些在这种情况下有用的工具?
发布于 2017-03-03 13:41:22
通常,您这样做的方式是异步处理请求,即通过回调函数,然后将这些回调函数排队,这样它们就不会冲突。
同步调用与异步调用
同步函数调用和异步函数调用有什么区别?
同步调用:调用一个函数并让它立即完成它的工作。相同的线程执行调用,调用一直阻塞直到函数完成/返回;因此:在它结束之前,什么都不能做。这是您通常在每个正常程序中所做的工作。
异步调用:将函数调用放在队列中,然后可以从同一个或另一个线程调用该函数。
通常,对于客户机/服务器应用程序,您从不使用同步调用来处理传输的数据。一旦你理解了这一点,你就会明白多线程是如何工作的,一切都会变得很简单,!
异步调用如何在服务器/客户端程序上工作?
例如,在Boost ASIO中,可以设置要在服务器/客户端接收数据时调用的函数。基本上,您要做的是告诉Boost Library:如果我的服务器接收到数据(比如std::string buffer),我希望您调用这个函数来处理这些数据。
(请注意,同步选择是您调用,并等待直到服务器接收到某件东西,而线程只是完全阻塞直到接收到某件东西。这一点都不方便!这就是为什么同步呼叫不是一个好主意的原因)。
如何从异步编程开始?
Boost ASIO提供了类io_service,它基本上是ASIO异步调用的处理程序。下面是一个例子:
void handle_async_receive(...) { ... }
void print() {
std::cout<<"Hello!"<<std::endl;
}
int main()
{
//some stuff
io_service.post(&print);
socket.connect(endpoint); //this is synchronous, so it connects and returns after the connection process is finished
socket.async_receive(buffer, &handle_async_receive);
io_service.post(&print);
io_service.run(); //this will block until the io_service queue is empty
}当您post时,所有的打印调用都不会发生。您只需将它们放到一个队列中,当您执行run() io_service时,它们将被执行。
多线程呢?
对于多线程,Boost ASIO中有一个名为strand的解决方案。在向io_service发布任何函数之前,您所要做的就是用一条链“包装”它。一个字符串队列函数调用,即使它们位于多个线程上。因此,它是一个非阻塞的解决方案,不像互斥。
发布于 2017-03-03 13:13:22
为了真正避免使用多线程,无论是自己还是通过像Boost.Asio这样的库间接地使用,我将使用轮询/select/epoll(选择您的颜色)监视服务器侦听套接字和所有客户端套接字。默认情况下,您的进程可以处于不超时的状态,等待发生套接字事件。
然后,这取决于您的服务器进程是否完成了所有的工作,那么您可能需要找到一种将大/长处理请求拆分成较小块的方法,以便给其他客户端一个机会/时间间隔。然后构建这些处理块的队列,检查没有等待的套接字,然后再次处理块,直到块队列再次为空。
如果繁重的工作(例如由数据库完成),将请求发送到数据库,检查套接字,检查来自DB服务器的答复等,直到请求被完全处理为止。
发布于 2017-03-03 13:01:29
我最好的建议是不要自己动手,除非你真的想做(也就是为了你的知识或学习)。
有各种各样的库应该完成这个任务,
boost.asio是其中之一。
https://stackoverflow.com/questions/42579412
复制相似问题