2010-07-02 12 views
2

배경 :TCP 메시지가 ACK 될 때까지 기다리는 방법

우리는 서버에 지속적 연결을 사용하는 클라이언트/서버 응용 프로그램이 있습니다.

Benchmarks는 새로운 연결 (암호화)을 설정하는 데 상당한 시간 (2.5 초)을 소비하는 대신 이미 열려있는 연결을 사용하는 것이 여러 번 더 빠르다는 것을 보여줍니다.

불행히도 이전 연결이 유효하지 않을 수 있습니다.

[ACK 또는 오류 메시지]를 보내는 시스템 수준의 결과를 기다리는 방법이 있습니까?

읽기를 기다렸다가 스트림 끝을 기다리는 것은 혼란을 야기합니다.

메시지가 패킷으로 분리 될 수 있습니다. 그것은 메시지의 어떤 부분이 받아 들여 졌는지 또는 전부인지 알기 위해서도 똑같이 잘 적응할 것입니다. 흥미로운 문제는 부실 연결입니다.

답변

1

불행히도 이전 연결은 일 수 있습니다.

경우에 따라 예외를 작성할 수 있습니다.

메시지 [ACK 또는 오류 중 하나]를 보내는 시스템 레벨의 결과를 기다려야하는 방법이 있는가? 읽기 대기 한 후 스트림의 끝을 받고

번호

혼란이 발생합니다.

누구와 혼동? 혼동을 다루는 코드는 입니다.입니다. 예기치 않은 EOS가 발생하면 피어가 연결을 종료했거나 중간 방화벽이있는 경우 처리해야합니다.

메시지가 개로 분할되어있을 수 있습니다.

전혀 관계가 없습니다. 당신은 그것이나 그것의 가시성을 통제하지 못합니다. 당신이 얻는 것은 EOS 나 예외에 의해 종료 된 바이트 스트림입니다. 메시지의 일부가 을 애크 경우 또는 모든 인 경우

그것은 하나 알고 똑같이 잘 내 목적에 맞게 것이다.

아니요. ACK는 피어의 TCP/IP 스택까지 도달했음을 의미합니다. 응용 프로그램에서 관심있는 부분은 피어 응용 프로그램에 들어 갔는지 여부이며 응용 프로그램 프로토콜 수준의 ACK를 통해 피어 응용 프로그램 만 알려줄 수 있습니다. TCP/IP ACK는 여기서 도움이되지 않습니다.

재미있는 문제는 부실 연결입니다.

그리고 다소 사소한 문제입니다. 당신은 코드에서 그것을 발견 할 수 있고 당신은 그것을 다룰 수 있습니다. 데이터베이스 공급 업체는 수십 년 동안 이러한 작업을 해오 고 있습니다. 로켓 과학이 아니며 TCP ACK에 대한 지식이 필요하지 않습니다.

+0

"ACK는 피어의 TCP/IP 스택까지 도달했음을 의미합니다." 어느 것이 나를 위해 충분합니다. 매우 일반적인 오류와 매우 드문 오류를 구분하려고합니다. – Joshua

+0

@ Joshua 당신이 그것을 감지 할 방법이 없기 때문에 그것은 당신에게 충분하지 않습니다. – EJP

0

TCP 통신을 처리하는 계층에서 ACK를 신경 쓰지 않아도됩니다. 그것이 레이어 3 이하의 작업입니다. 귀하의 프로토콜에 대해 항상 명령/응답 요청을하십시오. 성공 또는 오류 여부에 관계없이 응답이 있어야합니다. 성공에 대한 응답이 없다는 것을 해석하는 것은 위험한 일입니다. 깨는 커뮤니케이션이 같은 효과를 가져올 수 있기 때문입니다.

부패로 인해 무슨 뜻인지 정확히 모르겠습니다. TCP는 연결 지향 프로토콜이기 때문에 연결이 설정되어 있습니다. 그러므로 나는 당신에게 어떤 어려움이 있는지 알지 못합니다. 연결이 느슨하면 새로운 것을 만들려고 노력해야합니다.

+0

Stale은 오래된 방화벽이 오래 걸리지 만 어느 쪽도 아직 알지 못한다는 것을 의미합니다. – Joshua

+0

(또는 때때로 keepalives를 존중하지 않는 다른 사람에 의해) – Joshua

0

로컬로 연결이 끊어지고 OS가 로컬 오류를 스택에보고하지 않는 한 TCP 연결 자체가 더 이상 실행 가능하지 않은 경우 알려주지 않습니다. 재전송 타임 아웃 (here 참조)으로 인해 쓰기가 실패하면 연결이 끊어 졌음을 나타내는 '꽤 많은 시간'이 걸릴 수 있습니다. 이것은 물론 설계 상으로는 디자인이 당신이 원하는 것과 다를 가능성이 있습니다.

TCP keep alives를 사용해 볼 수도 있지만 IMHO는 이러한 노력을 기울일 가치가 없습니다. 가능한 경우 응용 프로그램 수준 ACK를 구현하는 것이 좋습니다. 그러면 응용 프로그램 수준 프로토콜에서 그것이 당신에게서 어떤 자료를 얻 자마자 응답. 그렇게 할 수없고 요청이 연결의 다른 쪽에서 응답을 이끌어 낸다면 연결이 죽었다 고 가정하기 전에 응답을 기다릴 준비가되어있는 시간을 기준으로 타이머를 간단히 설정할 수 있습니다. 타이머가 만료되면 연결을 종료하고 새 타이머를 설정합니다.

새 연결 시도를 시작하고 이전 연결에 대한 요청을 보낼 수도 있습니다. 이전 연결에서 응답을 받기 전에 새 연결을 사용할 수있게되면 새 연결에 대한 요청을 보낼 수 있습니다. 연결하고 오래된 것을 닫으십시오 ... 물론 이것은 이런 종류의 것을 처리 할 수있는 응용 프로그램에 의존합니다.

마지막으로 비활성 상태로 인해 연결이 끊어지는 경우 응용 프로그램 수준의 ping을 프로토콜에 추가 할 수 있습니다.이 ping은 다음과 같은 경우에 자주 메시지를 보내도록 설정할 수 있습니다. a) 연결이 활성 상태인지 확인하고 b) 라우터 또는 방화벽이 연결이 끊어진 것으로 생각하지 않도록하십시오.

관련 문제