2010-04-09 5 views
4

클라이언트 TCP 소켓을 특정 로컬 포트에 바인딩합니다. 소켓이 얼마 동안 TIME_WAIT 상태로 유지되는 상황을 처리하기 위해 소켓에서 setsockopt()SO_REUSEADDR을 사용합니다.클라이언트 TCP 소켓을 Winsock을 사용하여 특정 로컬 포트에 바인딩 할 때 SO_REUSEADDR은 아무런 영향을받지 않습니다.

Linux에서는 작동하지만 Windows에서는 작동하지 않으므로 이전 연결이 여전히 TIME_WAIT 인 경우 WSAEADDRINUSE에서 connect()으로 전화하십시오.

MSDN 클라이언트 소켓 일이 정확히 무엇을해야하는지 명확하지 않다 :

[...] 같은 포트 번호에 여러 개의 소켓을 바인드해야 서버 응용 프로그램의 경우, setsockopt (SO_REUSEADDR) 사용하는 것이 좋습니다. 클라이언트 응용 프로그램은 보통 bind를 호출 할 필요가 없습니다. -connect는 사용되지 않는 포트를 자동으로 선택합니다. [...]

어떻게이 문제를 방지합니까? 당신이 socket()와 소켓을 만들 때

+0

당신은 우리에게 말해 줄 수? – Jay

+0

@ 외부 시스템과의 인터페이스가 필요하므로 피할 수 없습니다. –

+0

Linux에서 클라이언트 소켓을 바인딩하기위한 작업 코드 조각을 공유 할 수 있습니까? –

답변

10

, 그것은 단지 유형과 프로토콜 패밀리가 있습니다. 이상적인 것은 bind() 로컬 주소 : 포트에도 있습니다.

당신이 일반적으로 언급 한 동일한 호스트에 마지막 연결 때 발생하는 오류 : 포트가 정상 종료 (FIN/ACK FIN/ACK)을하지 않았다. 이러한 경우 소켓은 일정 기간 (OS에 따라 다르지만 조정 가능) 동안 TIME_WAIT 상태로 유지됩니다. 다음 일이 같은 호스트와 같은 포트에 connect()하려고 할 때 무엇

, 그것은 등 기본 소켓의 이름/주소/포트/사용하지만이 조합은 좀비 소켓에 의해 이미 사용 중입니다. 이를 방지하려면 로컬 주소를 변경할 수 있습니다 포트는 해당 지역의 주소와 임의 포트 가득 sockaddr 구조체를 제공, 소켓 생성 후 bind()를 호출하여 연결을 설정하는 데 사용.

int main() { 
    int ret, fd; 
    struct sockaddr_in sa_dst; 
    struct sockaddr_in sa_loc; 
    char buffer[1024] = "GET/HTTP/1.1\r\nHost: www.google.com\r\n\r\n"; 

    fd = socket(AF_INET, SOCK_STREAM, 0); 

    // Local 
    memset(&sa_loc, 0, sizeof(struct sockaddr_in)); 
    sa_loc.sin_family = AF_INET; 
    sa_loc.sin_port = htons(LOCAL_RANDOM_PORT); 
    sa_loc.sin_addr.s_addr = inet_addr(LOCAL_IP_ADDRESS); 

    ret = bind(fd, (struct sockaddr *)&sa_loc, sizeof(struct sockaddr)); 
    assert(ret != -1); 

    // Remote 
    memset(&sa_dst, 0, sizeof(struct sockaddr_in)); 
    sa_dst.sin_family = AF_INET; 
    sa_dst.sin_port = htons(80); 
    sa_dst.sin_addr.s_addr = inet_addr("64.233.163.104"); // google :) 

    ret = connect(fd, (struct sockaddr *)&sa_dst, sizeof(struct sockaddr)); 
    assert(ret != -1); 

    send(fd, buffer, strlen(buffer), 0); 
    recv(fd, buffer, sizeof(buffer), 0); 
    printf("%s\r\n", buffer); 
} 

UPDATE는 (희망) 특정 로컬 포트를 사용하는 등 요구 사항이다, 그래서 당신의 소켓이 close/closesocket에 차단하지 않습니다 l_onoff=1l_linger=0SO_LINGER을 설정하는 것이 좋습니다 그냥 대기중인 데이터를 무시하고합니다 fd를 닫으십시오. 최후의 수단으로이 레지스트리 키의 값을 변경하여 TIME_WAIT 지연을 조정할 수 있습니다 (매우 실망를!) :

HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\TcpTimedWaitDelay 
+0

그래, 그 뒤에있는 기계공을 알고 있지만, 불행히도, 그건 옵션이 아니야. 나를 위해. I * do * 매번 동일한 로컬 포트에 바인딩해야합니다 (질문에 대한 내 의견 참조). –

+0

TIME_WAIT를 낮은 값으로 조정해도됩니까? – jweyrich

+1

IMHO 결코 처음 고려해서는 안됩니다 ... –

0

을 당신은 당신이 실행중인 윈도우 플랫폼을 지정하지 않는 등의 일에 영향을 미칠 수 당신이 (? 즉, 당신은 admin입니다)에서 실행하고있는 보안 주체는 ...

이 도움이 될 수 있습니다 http://blogs.msdn.com/wndp/archive/2005/08/03/Anthony-Jones.aspx

+0

Windows XP, admin이 아닙니다. –

0

조심 로컬 포트를 바인딩에 루프백 주소 "127.0.0.1을 사용하지 "또는 연결 시간 초과가 발생합니다. sa_loc.sin_addr.s_addr을 전혀 채우지 않는 것이 좋습니다. 정상적으로 작동합니다. 당신이 포트에 클라이언트 소켓을 바인딩 할 이유

관련 문제