2015-01-31 4 views
3

기존의 HTTP 서버에 정말로 기본적인 프록시 서버를 구축하고 있습니다. 들어오는 연결은 대기열에 추가되고 대기중인 스레드의 다른 대기열에있는 하나의 스레드로 신호가 전송됩니다. 이 스레드는 들어오는 연결을 대기열에서 가져 와서 처리합니다.다중 스레드 다중 소켓 send/recv 동시 수행

문제는 프록시가 실제로 입니다. 실제로는이 느립니다. reddit.com을 1 분 정도 천천히로드하십시오. 그리고 그것은 동시에 아무 것도하지 않는 것이 분명합니다. 프록시 기능은 다음과 같습니다.

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 분 동안 차단 되었기 때문입니다.

+1

send() 및 recv() 호출이 실제로 보내거나받은 데이터의 바이트 수를 추적하지 않습니다. send() 및 recv()의 반환 값을 검사하고 실제로 보내거나받은 바이트 수에 따라 올바른 작업을 수행해야합니다. 전송 또는 수신 요청 바이트 수보다 적을 수 있습니다. –

+1

또한 아래쪽에서 send()를 호출하여 (n) 바이트를 보내고 있지만 connect() 호출의 반환 값에 의해 마지막으로 설정 되었기 때문에 AFAICT n은 아마 0 일 것입니다. 0 바이트를 보내는 것이 아무 것도하지 않는다는 것을 감안할 때 코드가 전혀 작동하지 않는다는 것에 놀랍니다. –

+0

죄송합니다. 질문에서 코드를 지나치게 단순화했습니다. 내가 지금해야 할 방식으로 편집했습니다. 느린 속도로 계속 실행 중임 –

답변

-1
  1. 처음에는 연결을 수정하고 연결 시간을 소비 할 수 있다고 생각합니다. 하나의 연결 타임 아웃은 75 초입니다. 그래서 당신은 noblocking socket으로 수정 한 다음 select를 사용하여 결과를 기다릴 수 있습니다. (이 방법을 비동기 연결이라고합니다.)

  2. 연결 오류가 반환되면 소켓을 닫아야합니다. 소켓 연결 오류가 발생하면 소켓 사용할 수 없게됩니다. 그것을 닫고 연결할 새 소켓을 만들어야합니다.

  3. 스트림 소켓이기 때문에 send 및 recv return을 테스트해야합니다. 데이터가 충분하지 않거나 더 많은 데이터가 반환 될 수 있습니다. 따라서 데이터를 압축하고 압축을 풀어야합니다.

  4. setsockopt를 사용하여 시간 초과를 설정하면 완벽하지 않습니다. 당신도 선택을 사용할 수 있습니다. 시간 정확도 선택은 setsockopt보다 좋습니다.

나는 내 대답이 당신을 도울 수 있기를 바랍니다.