2008-10-08 2 views
1

패킷 배달이 영구적으로 실패 할 경우 TCP/IP는 오류를 어떻게보고합니까? 필자가 보았던 모든 Socket.write() API는 바이트를 기본 TCP/IP 출력 버퍼로 전달하고 비동기 적으로 데이터를 전송합니다. 그렇다면 TCP/IP는 패킷 전달이 영구적으로 실패한 경우 (예 : 대상 호스트에 더 이상 도달 할 수없는 경우) 개발자에게 알리는 방법은 무엇입니까?TCP/IP는 어떻게 오류를보고합니까?

보낸 사람이 원격 끝에서 확인을 기다려야하는 모든 프로토콜에는 오류 메시지가 표시됩니다. 그러나 보낸 사람이 대상에서 바이트를 읽을 필요가없는 프로토콜의 경우에는 어떻게됩니까? TCP/IP가 자동으로 실패합니까? 아마도 Socket.close()는 오류를 반환 할 것입니까? TCP/IP 사양이 이것에 대해 아무 말도하지 않습니까?

답변

5

TCP/IP는 안정적인 바이트 스트림 프로토콜입니다. 모든 바이트가 수신자에게 도착하거나 오류 표시가 나타납니다.

오류 표시는 닫힌 소켓 형식입니다. 전송 패턴을 누가 (누가)하는지에 관계없이 바이트를 전달할 수 없으면 소켓이 닫힙니다.

문제는 소켓을 어떻게 닫을까요? 읽지 않는다면 닫힌 소켓에 쓰려고 할 때 오류가 발생합니다 (ECONNRESET errno로 생각합니다).

다른 파일 핸들에서 입력을 기다리거나 기다릴 필요가있는 경우 대기중인 소스 목록에 소켓을 포함시키는 select() 호출에서 기다리는 것이 좋습니다. 당신이 아무것도받을 것으로 기대하지 않는다면). select()가 소켓이 읽기 호출을 할 준비가되었다고 나타내면 -1 반환을 얻을 수 있습니다 (ECONNRESET으로 생각합니다).

이 오류를 클린 닫기 (예 : 다른 프로그램 종료)와 구별하는 방법은? errno 값으로 충분할 수 있습니다. 정상적으로 종료하지 못하도록 오류를 구분하십시오.

문제의 모호하지 않은 표시를 원할 경우 소켓 계층 위에 응용 프로그램 수준 프로토콜을 구축해야합니다. 예를 들어, "ack"메시지는 수신자가 보낸 사람에게 돌아갔습니다. 그런 다음 더 높은 수준의 응용 프로그램 프로토콜 (보낸 사람이 승인을받지 못함)을 위반하면 오류가 닫히고 닫히는 것을 확인할 수 있습니다.

4

소켓 API는 피어에 의해 수신 확인 된만큼 정확히 몇 바이트가 수신되었는지를 작성자에게 알릴 방법이 없습니다. 성공적인 shutdown 또는 close 중 하나라도 존재한다는 보장은 없습니다.

TCP/IP 사양은 거의 항상 소켓 API 인 응용 프로그램 인터페이스에 대해 아무런 언급이 없습니다.

SCTP은 이러한 단점을 해결하기 위해 시도되는 TCP의 대안입니다.

+0

SCTP가 매우 멋지다! TCP/IP에서 SCTP로 웹을 마이그레이션하는 방법에 대해 궁금합니다. 압도적 인 복잡성을 가진 작업처럼 들립니다. – Gili

0

send()로 실패한 소켓에 쓰기를하면, 보내진 바이트 수를 다시 얻게됩니다. 이 값이 보내려는 바이트 수와 일치하지 않으면 문제가있는 것입니다. 또한 실패한 소켓에 쓸 때 SIGPIPE가 다시 발생합니다. 소켓 처리를 시작하기 전에 SIGPIPE를 얻을 때 경고 할 수있는 신호 처리기가 있어야합니다.

소켓에서 읽는 중이라면 정말로 알람으로 포장해야 시간을 초과 할 수 있습니다. "alarm (timeout_val); recv(); alarm (0)"과 같습니다. recv의 리턴 코드를 점검하고, 0이면 연결이 닫혔 음을 나타냅니다. 음의 반환 결과는 읽기 실패를 나타내며 errno를 확인해야합니다.

+0

send()가 차단 기능입니까? 보낸 바이트 수를 반환하기 전에 실제로 승인을 기다리고 있습니까? 아니면 단순히 바이트를 출력 버퍼에 덤프하고 즉시 반환합니까? – Gili

0

TCP는 인터넷의 중심 인 IP 프로토콜을 기반으로하며 라우팅을 구동하는 많은 상호 운용성을 제공합니다. 라우팅은 소스에서 대상으로 패킷을 가져 오는 방법을 결정합니다. IP 프로토콜은 보낸 사람에게 전달하지 못한 패킷의 경우 ICMP (Internet Control Message Protocol)를 통해 오류 메시지를 보낸 사람에게 다시 보내야한다고 지정합니다. 이러한 이유로 TTL (Time To Live) 필드가 0으로 감소하여 패킷이 라우팅 루프에 걸리거나 패킷 충돌로 인해 버퍼 오버런이 발생하여 패킷이 끊어지는 경우가 있습니다. 다른 사람들이 말했듯이 소켓 API의 책임은 IP 계층에서 이러한 오류를 TCP 계층의 네트워크와 상호 작용하는 응용 프로그램에 전달하는 데 사용됩니다.