2011-08-19 2 views
0

기본 HTTP 클라이언트를 작성 중이며 문제가 발생했습니다. 일부 HTTP 서버는 리셋을 강제 실행하여 피어 "오류. 많은 HTTP 서버가 정상적으로 연결을 닫습니다. 아무도 연결을 유지하지 못하는 것 같습니다.HTTP 클라이언트가 일부 서버에서 "피어 (Connection)에 의한 연결 재설정"(TCP RST)을 받고 있습니다.

그러나 매우 비슷한 소스 코드를 사용하는 HTTP 클라이언트는 동일한 서버에 대한 연결이 정상적으로 닫히거나 활성 상태로 유지되므로 내 클라이언트라고 확신합니다.

겉으로보기에는 일관성없는 문제의 원인은 무엇입니까?

관련 코드 : 몇 가지 조사 후

/* socket */ 
if ((context->socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { 
    perror("Failed to create socket"); 
    exit(-1); 
} 

/* connect */ 
if (connect(context->socket, &context->tx_addr, sizeof(struct sockaddr)) != 0) { 
    perror("Couldn't connect to server"); 
    exit(-1); 
} 

/* create header */ 
snprintf(context->packet, BUFF_SIZE, 
     "GET %s HTTP/1.1\r\n" \ 
     "Host: %s\r\n\r\n", 
     conf->request, conf->host); 

/* send header */ 
if ((sendto(context->socket, context->packet, BUFF_SIZE, 0, 
      NULL, 0))) != BUFF_SIZE) { 
    perror("Failed to send"); 
    exit(-1); 
} 

/* receive response */ 
do { 
    if ((received = recvfrom(context->socket, context->packet, BUFF_SIZE, 0, NULL, 
          NULL)) < 0) { 

     /* THIS is where RST occurs with some servers */ 

     perror("Failed to receive"); 
     exit(-1) 
    } 

    if (received >= 0)  
      context->packet[received] = '\0'; 
    printf("%s", context->packet); 

} while (received > 0); 

답변

0

, 그것은 내 HTTP 요청 형식이 잘못되었다 명백하게되었다.

문제는이 코드에있다 :

/* create header */ 
snprintf(context->packet, BUFF_SIZE, 
     "GET %s HTTP/1.1\r\n" \ 
     "Host: %s\r\n\r\n", 
     conf->request, conf->host); 

/* send header */ 
if ((sendto(context->socket, context->packet, BUFF_SIZE, 0, 
      NULL, 0)) != BUFF_SIZE) { 
    perror("Failed to send entire buffer"); 
    exit(-1); 
} 

버퍼에서 BUFF_SIZE 바이트 snprintf와 헤더를 만들 때 우리가 거의 확실히 전체 버퍼를 기입하지 않습니다에도 불구하고, 전송되는 것을 알 수 있습니다. 생성 된 헤더를 처리하는 쓰레기도 전송되었습니다. 일부 서버는 잘못된 요청을 무시하고 다른 서버는 연결을 포기하고 다시 연결 (RST)합니다.

는 간단하게 문제를 해결하기 위해이 같은에 송신 코드를 변경 :

/* assuming context->packet is a string */ 
int len = strlen(context->packet); 
int sent = 0, total = 0; 

while (total < len) { 
    if ((sent = sendto(context->socket, context->packet + total, 
         len - total, 0, NULL, 0)) <= 0) { 
     perror("Failed to send"); 
     exit(-1); 
    } 
    total += sent; 
} 
+0

'sendto를을 (...) = BUF_SIZE' 잘못입니다!. 첫째로, 당신은 지금 그것보다 적게 보내고 있습니다. 둘째로, TCP는 버퍼에 버퍼를 줄 수 있습니다. –

+0

내가 실수하지 않는다면 깃발에 달려있다. 즉, 플래그가없는 sendto는 요청 된 양이 write()처럼 보내질 때까지 차단할 것이다. – TimCinel

+1

아니요, 소켓의 송신 버퍼에서 사용할 수있는 모든 공간에 쓰고 반환합니다. 간단한 경우에는 이것을 볼 수 없지만 트래픽이 많을수록 짧은 기록이 발생합니다. –

관련 문제