2009-05-28 3 views
1

회사에서 생산 한 장치의 신호를 수신하는 네트워크 서버에 문제가 발생했습니다. 장치는 방금 사용한 원본 포트를 때때로 재사용합니다. 이로 인해 SYN이 서버에 의해 삭제됩니다. 그런 다음 장치는 이전 소켓이 서버의 TIME_WAIT에서 벗어날 때까지 재 시도합니다. 서버가 SYN-ACK를 보낸다.Java 네트워크 서버 및 TIME_WAIT

서버는 Java로 작성되었습니다. 안타깝게도 필드를 올바르게 순환하도록 장치를 수정하는 것은 옵션이 아니며 기존 필드를 업데이트하는 것은 옵션이 아닙니다. 이전 소프트웨어는 C++로 작성되었으며 Windows TCP 스택의 목록에서 TIME_WAIT 포트를 제거했습니다.

Windows에서 Java의 TIME_WAIT을 우회하는 방법에 대해 조언을 해 줄 사람이 있습니까?

편집 : 나는 실제로 장치가 최근에 사용 된 포트를 재사용한다는 것을 Wireshark에서 확인했습니다. 받은 후

socket = new ServerSocket(); 
socket.setPerformancePreferences(3, 2, 1); 
socket.setReuseAddress(true); 
socket.setSoTimeout(CLIENT_READ_TIMEOUT); 
socket.bind(new InetSocketAddress(group.getPort()), MAX_TCP_BACKLOG); 

을 그리고 클라이언트 소켓이 설정 한 다음했습니다 : 서버 소켓에

나는 다음과 같은 옵션을 사용하고

내가 모두 true와 false로 SO_LINGER를 시도
Socket client = server.accept(); 
client.setKeepAlive(false); 
client.setSoLinger(true, 0); 
client.setReuseAddress(true); 
client.setTcpNoDelay(true); 
client.setSoTimeout(CLIENT_READ_TIMEOUT); 

, 동일한 추적 결과가 표시됩니다. CLIENT_READ_TIMEOUT은 10 초로 설정됩니다.

답변

3

TIME_WAIT을 피하기 위해 옛 하지 권장 트릭 { 1, 0 }SO_LINGER 소켓 옵션을 설정합니다 - 다음 대신 일반 플러시/사방 교환 순서를 일의 RST를 전송 close, 따라서 TIME_WAIT을 피하는 모두 함께 (경고 - 당신은 여전히 ​​보낼 버퍼에있는 꼬리를 잃을 수도 있습니다.)이 Java에서 할 수 있는지 여부를 말할 수 없습니다.

편집 : tcpdump으로 클라이언트가 실제로 원본 포트 번호를 다시 사용할 수 있는지 확인할 수 있습니까? 그렇지 않은 경우 Jon이 지적한대로 SO_REUSEADDR 청취 소켓 옵션의 고전적인 사례 일 수 있습니다.

4

건물 니콜라이의 대답에,

Socket s; 
... 
s.setSoLinger(true,0); 

자바에 해당하는 것입니다.

EDIT :보고 싶은 또 다른 사항은 setReuseAddress (true)입니다.

0

서버는 이전 원본 포트를 사용하는 새 세션의 세션과 이전 세션의 재전송을 구분할 수 없기 때문에 클라이언트의 SYN 패킷을 무시합니다. 서버의 TIME_WAIT 상태를 우회하는 경우, 제어 블록 테이블의 TIME_WAIT 상태 항목을 고갈시키기위한 시스템 타이머 간격을 설정하여 서버가 이미 종료 된 세션에 대해 SYN 재전송을 어떻게 올바르게 무시합니까?

관련 문제