다음 STCP 코드 조각은 내가 관찰한 문제를 보여 줍니다. 읽을 데이터가 있을 때까지 recv 호출을 차단한 다음 수신된 데이터를 처리하고 recv를 다시 호출하여 더 많은 데이터(또는 오류)로 반환하거나 차단합니다. 오류가 발생하면 recv가 -1을 반환하고 오류 코드가 오류 변수에서 설정됩니다. 코드가 확인된 것처럼 보이나요?
while (1) { cBytes = recv (socks1, buffer, BUFFERLEN, 0); if (cBytes == -1) { perror ("Unexpected error at recv"); exit (errno); } else printf ("number of bytes received : %dn", cBytes); } |
코드는 원격 피어가 연결을 우아하게 닫히지 않을 것이라고 가정합니다. 원격 피어가 우아하게 닫히면 닫거나 종료 함수를 호출하는 경우 recv는 0바이트를 반환하여 로컬 응용 프로그램에 이를 나타냅니다. 이력서에 대한 후속 호출은 0 바이트를 반환계속됩니다. 그 결과 코드가 이제 아무 것도 하지 않는 타이트한 루프에 있습니다. 예를 들어
수신된 바이트 수 : 8 수신된 바이트 수 : 57 수신된 바이트 수 : 16 수신된 바이트 수 : 1 수신된 바이트 수 : 1 수신된 바이트 수 : 0 수신된 바이트 수 : 0 수신된 바이트 수 : 0 수신된 바이트 수 : 0 수신된 바이트 수 : 0 . . . . . |
응용 프로그램 프로토콜이 원격 피어가 연결을 우아하게 닫히지 않도록 지시하더라도 연결이 정상적으로 닫히지 않도록 보장할 수 없습니다. 원격 응용 프로그램에 버그가 있거나 원격 TCP 스택이 응용 프로그램 프로세스가 종료될 때 우아할 수 있는 닫을 수 있습니다. 또는 다른 응용 프로그램이 연결을 만든 다음 예상 응답을 얻지 못했을 때 닫을 수 있습니다. 포트 스캔 또는 배너 잡기를 수행하는 보안 감사(또는 악의적인 사용자)도 우아한 닫을 수 있습니다. 결론은 항상 0 바이트의 경우를 처리해야한다는 것입니다.
while (1) { cBytes = recv (socks1, buffer, BUFFERLEN, 0); if (cBytes <= 0) { if (cBytes < 0) { perror ("Unexpected error at recv"); exit (errno); } else { printf ("received closen"); close (socks1); exit (0); } } else printf ("number of bytes received : %dn", cBytes); } |
수신된 바이트 수 : 28 수신된 바이트 수 : 2 수신된 바이트 수 : 58 마감 |