多线程多插槽同时发送/接收

时间:2015-01-31 15:22:43

标签: c++ multithreading sockets http-proxy

我正在为我之前存在的HTTP服务器构建一个非常基本的代理服务器。传入连接被添加到队列中,并且信号被发送到另一个等待线程队列中的一个线程。该线程从队列中获取传入连接并处理它。

问题是代理真的真的慢。 1分钟加载reddit.com慢。它显然没有同时做任何事情。这是代理功能:

void ProxyConnection::handleConnection() {
    if (req->getRequestMethod().compare("GET") == 0) {

        addrinfo host_info;
        addrinfo *host_info_list;
        int proxy_sockfd;
        ssize_t n;

        memset(&host_info, 0, sizeof host_info);

        host_info.ai_family = AF_INET;
        host_info.ai_socktype = SOCK_STREAM;

        n = getaddrinfo(req->getRequestParam("Host").c_str(), "80",
                        &host_info, &host_info_list);
        if (n == -1)
            cout << "ERROR: getaddrinfo" << endl;

        proxy_sockfd = socket(host_info_list->ai_family,
                              host_info_list->ai_socktype,
                              host_info_list->ai_protocol);

        if (proxy_sockfd == -1)
            Utils::error("ERROR creating socket");

        n = connect(proxy_sockfd, host_info_list->ai_addr,
                    host_info_list->ai_addrlen);
        if (n == -1)
            cout << "ERROR connecting" << endl;

        // send the request to the destination server
        send(proxy_sockfd, req->getSource().c_str(),
             req->getSource().length(), 0);

        struct timeval tv;
        tv.tv_sec = 5;
        tv.tv_usec = 0;
        setsockopt(proxy_sockfd, SOL_SOCKET, SO_RCVTIMEO,
                   (char *)&tv,sizeof(struct timeval));

        // receive the destination server's response, and send that
        // back to the client
        while ((n = recv(proxy_sockfd, buf, MAX_BUF, 0)) > 0) {
            send(sockfd, buf, n, 0);
        }
    }
}

如何将其配置为并行执行?正如你所看到的,我已经在recv()函数上设置了5秒超时,因为有时它会被不必要地阻塞(即它已经收到它将要接收的所有内容,但它一直在等待)长达一分钟!

1 个答案:

答案 0 :(得分:-1)

  1. 首先我认为你可以修改连接,连接消耗时间。一个连接超时是75秒。所以你可以将它修改为noblocking套接字,然后使用select来等待结果(这个方法称为异步连接。)

  2. 如果连接返回错误,则必须关闭套接字。因为当套接字连接发生错误时,套接字变得不可用。你必须关闭它并创建一个新的套接字才能连接。

  3. 因为您是流套接字,所以必须测试send和recv返回。它可能会为您返回不够的数据或更多数据。所以你必须打包并打开数据包。

  4. 使用setsockopt设置超时并不完美。你也可以使用select。选择时间准确度优于setsockopt。

  5. 我希望我的回答可以帮到你。