2015-01-31 4 views
3

Я создаю действительно базовый прокси-сервер в моем уже существующем HTTP-сервере. Входящие соединения добавляются в очередь, и сигнал отправляется в один поток в другой очереди ожидающих потоков. Этот поток принимает входящее соединение из очереди и обрабатывает его.Многопоточный множественный сокет send/recv одновременно

Проблема в том, что прокси действительно действительно slow. 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); 
     } 
    } 
} 

Как настроить это для параллельного выполнения? Как вы можете видеть, я установил 5-секундный тайм-аут в функции recv(), потому что иногда он блокировал ненужно (т. Е. Он уже получил все, что собирался получать, но он продолжал ждать) на минуту!

+1

Вы не отслеживаете, сколько байтов данных посылает или принимает вызовы send() и recv(). Вам нужно проверить возвращаемые значения send() и recv() и сделать правильную вещь в зависимости от того, сколько байтов они * действительно отправили или получили, что может быть меньше количества байтов, которые вы просили отправить или получить. –

+1

Также похоже, что внизу вы вызываете send() для отправки (n) байтов, но AFAICT n, вероятно, будет 0, так как он был последним установленным значением для вызова connect(). Учитывая, что отправка 0 байтов ничего не делает, я удивлен, что код работает вообще ... –

+0

Извините, я слишком упростил код в вопросе. Я отредактировал его так, как сейчас. Он все еще работает так же медленно, как и раньше. –

ответ

-1
  1. Сначала я думаю, что вы можете изменить соединение, подключить время потребления. один тайм-аут подключения - 75 секунд. поэтому вы можете изменить его на noblocking socket, а затем использовать select для ожидания результата (этот метод называется Asynchronous connect.)

  2. Если ошибка возврата соединения вы должны закрыть сокет. Потому что, когда сокет подключается, произойдет ошибка, сокет становятся недоступными. вы должны закрыть его и создать новый сокет для подключения.

  3. поскольку вы являетесь сокетом потока, вы должны протестировать возврат отправки и возврата. он может вернуть не достаточно данных или больше данных для вас. поэтому вы должны упаковать и распаковать данные.

  4. использование setsockopt для установки таймаута не является совершенным. вы также можете использовать select. выбор Точность времени лучше, чем setsockopt.

Надеюсь, мой ответ может вам помочь.