2012-09-04 2 views
7

TCP 소켓을 통해 클라이언트 - 서버 통신을 테스트하고 있습니다. 나는 C로 서버를 썼고 리눅스 머신에서이 서버를 실행했고 테스트를 위해 nc을 클라이언트로 사용하고있다.닫힌 소켓의 두 번째 전송시에만 깨진 파이프

서버는 클라이언트와 처음 메시지를 교환 한 후 응답을받지 않고 클라이언트에 주기적으로 일부 메시지를 보냅니다. 나는 클라이언트를 죽이면

, I는 서버에서 수행 한 첫 번째 send()EPIPE 오류와 함께 실패하지만, 이것은 단지 클라이언트가 간 후에 두 번째 send()에서 밝혀 것을 기대! 첫 번째 send()은 클라이언트를 죽인 후 1100 바이트를 성공적으로 보낼 수 있습니다. 다음 send() 작업은 ex3ct21으로 끝나는 EPIPE으로 끝납니다.

이 동작을 설명 할 수있는 사람이 있습니까? 사실 TCP/IP 스택에 쓰기 때문에 스택 할 때까지 할 수 있습니까? 그렇다면 어떻게 연결 상태를 확인할 수 있습니까? 피어가 아직 있는지 확인하십시오.

답변

4

일반 TCP 연결은 4 방향 핸드 셰이크입니다.

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

당신이 FIN 세그먼트가 서버 및 서버 프로토콜 스택에 클라이언트 측에서 전송되는 클라이언트를 살해하는 ACK 보냅니다.

여기서 서버가 데이터를 읽으려고하면 읽기 호출은 0 값을 반환하므로 서버 프로그램은 피어가 닫혔다는 것을 이해할 수 있고 이후에 연결 소켓을 정상적으로 닫을 수 있습니다. 이렇게하면 FIN이 전송되고 클라이언트 측에서 마지막 ACK을받은 후 정상 4 방향 핸드 셰이크가 완료됩니다.

(경기 수는 Q http://www.faqs.org/faqs/unix-faq/socket/의 2.1 읽기) 그러나 여기에는 서버에서 데이터를 작성하는, 그래서 서버는 데이터를 전송 한 후 클라이언트에서 RESET을 받고있다. 따라서 두 번째 전송에있는 첫 번째 전송 작업 후에 오류가 발생합니다.

그래서, pl. 클라이언트 쪽 에서 갑자기의 연결을 닫으십시오. linger 옵션과 timeout을 0으로 설정하여 send on의 첫 번째 호출에서 오류 (EPIPE와 다를 수 있음)를 얻을 수 있습니다 서버 측. (이것은 recommnended 방법이 아닙니다하지만이 특별한 경우에 이해를위한)

Try the following option of nc, nc -L 0 to set the linger option and timeout to 0 

(내가 PL, 노스 캐롤라이나의이 옵션을 시도하지 않았습니다.이 링크에서 자세한 내용을 확인 http://docs.oracle.com/cd/E23824_01/html/821-1461/nc-1.html)

상기 사이트의 nc의 예,

Connect to TCP port, send some data and terminate the connection with 
TCP RST segment 
(instead of classic TCP closing handshake) by setting the linger option and 
timeout to 0: 

$ echo "foo" | nc -L 0 host.example.com 22 
+0

답장을 보내 주셔서 감사합니다. 명확하고 명확합니다. 불행히도 나는 리눅스 시스템의 명령이 그것을 지원하는 것 같지 않기 때문에 당신이 제안한 nc 옵션을 테스트 할 수 없다.그건 그렇고 당신이 가르쳐 준 문서와 당신이 준 설명은 분명하고 유용합니다. 감사! – Igor

관련 문제