2011-11-24 2 views
10

안녕하세요, TLPI (Linux 프로그래밍 인터페이스)를 읽고 있는데 connect()에 대한 질문이 있습니다.TCP 소켓에 대해 connect() 블록을 사용합니까?

내가 알고 있듯이 보류중인 연결 번호가 "backlog"에 도달하지 않으면 connect()가 즉시 반환합니다. 그리고 그렇지 않으면 차단됩니다. (그림 56-2에 따라)

그러나 TCP 소켓의 경우 서버 측 accept()가 호출 될 때까지 항상 차단됩니다 (그림 61-5 참조).

맞습니까? 예제 코드 (p.1265)에서 listen()을 호출하여 특정 포트를 수신 한 다음 accept()를 호출하기 전에 해당 포트에 대한 connect()를 호출합니다.

이 경우 connect() 블록을 영원히 연결하지 않습니까? 그렇습니다.

감사합니다.

+0

이것이 figure 56-2가 실제로 보여주는 것 인 경우, 잘못된 것입니다. – EJP

답변

19

네트워킹과 관련하여 거의 즉각적인 문제는 없으며, 이론적으로 즉시 수행해야하는 작업은 실제로는 수행되지 않을 수도 있으며, 어떤 경우에는 전송 끝 시간이 끝날 수도 있습니다. 소켓 기술자가 비 블록 모드로 전환하지 않는 한

그러나 TCP 소켓에

  • 은 연결() 차단 작업입니다.

  • OS는 TCP 핸드 셰이크를 처리하고 핸드 셰이크가 끝나면 connect()가 돌아옵니다.

  • 성공한 TCP 핸드 셰이크는 서버 응용 프로그램에 대기하고 나중에 언제든지 받아 들일 수 있습니다 (즉, 은 다른 쪽이 accept()를 호출 할 때까지 차단되지 않습니다).

+0

단지'connect'를 추가하고 서버가'accept'를 호출하지 않고 핸드 쉐이크를 기다리고 싶다면 두 가지 이유가 있습니다 : 첫 번째는 클라이언트 쪽에서 핸드 쉐이크 후에 연결된다는 것입니다. 두 번째 이유는 핸드 셰이크 사이에 임의의 시간을 전달할 수 있기 때문이며 서버가 '수락'을 호출하기 전에 실제로 영원 할 수 있기 때문입니다. –

+1

나머지 답변이 없어도 '즉시'는 거의 없습니다. 혼자서 +1을 보증합니다. 이는 논 블로킹 모드에서도 많은 작업에서 마찬가지입니다. 때때로 당신이 정말로 그것을 기대하지 않는 것들에 대해서조차도 때때로 놀라운 오랜 시간이 될 수 있습니다. – Damon

+0

@JoachimPileborg @nos 서버가'accept()'를 호출하기 전에'connect()'가 반환하면 서버가'accept()'를 호출하기 전에 클라이언트가'send()'를 시도하면 어떻게 될까요? – Flash

3

connect은 기본적으로 차단 호출이지만 SOCK_NONBLOCK 플래그를 socket으로 전달하여 차단하지 않을 수 있습니다.

+4

또는 더 일반적으로 O_NONBLOCK과 함께 fcntl의 "전통적인"BSD 소켓 함수를 사용하십시오. SOCK_NONBLOCK은 Linux에 따라 다릅니다. – MarkR

2

TCP 3 방향 핸드 셰이크가 끝날 때까지 블록합니다. 수신 측의 핸드 셰이크는 커널의 TCP/IP 스택에 의해 처리되고 사용자 프로세스에 알리지 않고 완료됩니다. 핸드 셰이크가 완료된 후에 만 ​​(그리고 초 기자가 connect() 호출에서 이미 반환 할 수 있음), 사용자 프로세스의 accept()가 새 소켓을 선택하여 반환 할 수 있습니다. 핸드 셰이크를 완료하기 위해 accept()를 기다리지 않아도됩니다.

이유는 간단합니다. 연결을 청취하는 단일 스레드 프로세스가 있고 연결 설정을 위해 accept()를 기다려야하는 경우 다른 요청을 처리하는 동안 TCP SYN에 응답 할 수 없습니다. 초기화 측의 TCP 스택이 재전송되지만 적당히로드 된 서버 확률이 높으면이 재전송 된 패킷은 accept()가 보류 상태 인 동안 계속 도착하고 다시 삭제되므로 추한 지연과 연결 시간 초과가 발생합니다.

관련 문제