connect 시 connection timed out 해결방안
글쓴이: hbsnow / 작성시간: 토, 2003/08/23 - 2:50오후
A <-> SERVER
가상ip, 방화벽 체크 시도를 위해
A가 서버로 CONNECT를 하고나서 A가 BIND하고 LISTEN한 소켓에 포트를 SEND 해줍니다
그러면 SERVER는 A가 알려준 PORT로 CONNECT를 수행해보면 A가 가상 IP인지 방화벽내에 있는지를 알수 있을것입니다.
가상아이피를 가진 A가 접근했을때 Connect를 하면 리턴되기까지 많은 시간이 소요되며 리턴값은 connection timed out입니다.
고정아이피는 Network is unreachable 이라 리턴이 바로 됩니다.
접근이 불가능한건 매한가지 인데 리턴되는 형태는 다른것 같습니다.
고수님들의 조언을 구합니다
Forums:
질문이 애매하네요.
조언이라는게
서버에서 A로 접근 할 방법을 말씀하시는건가요?
글의 내용으론 잘 이해하기 힘들군요.
서버에서 방화벽 뒤나 가상 IP 인 A 의 listen 포트에 접근한다는건 불가능한거 아닌가요?
그렇기 때문에 ftp 에 passive 모드라고 것도 있는거 아니였나요?
라고 이론적으로 생각하는데
e donkey 같은 경우 방화벽 같은게 있어서 어떻게 p2p 로 통신 하는 것 같기도 하던데....
전엔 그냥 그러려니 하고 넘어갔는데 지금 생각하니깐 저도 참 궁금하네요 ^^;
이런.. 답변이 하나도 안됐군여.
어쨌든 전 방화벽 뒤나 가상 ip 인 A 컴퓨터로 서버가 접속하는건 불가능이라고 생각하는데요...
(방화벽 뒤 의 컴에 접속이 가능하면 방화벽이라 할 수 없죠 그걸 막는게 방화벽인데....)
흠... 이 질문이 아니시라면... timeout 이 반환되는 시간이 넘 길어서 문제다. 좀 더 빠르게 반응을 얻을 수 없냐? 가 질문인걸까요? ^^;;
그럼 그냥 connection timeout 값을 작게 줄이면 어느정도 해결이 될 것 같은데.....
음...
간단히 애기해서
고정IP와 가상 IP에 대한 connect() 리턴값이 다르다는겁니다.
존재하지 않는 고정IP, 존재하지 않는 가상 IP에 각각 connect()를 시도하면 존재하지 않는 고정IP쪽은 "도착불가" , 존재하지 않는 가상IP쪽은 "타임아웃" 이 리턴된답니다.
그 이유가 일단 궁금하구요..
두번째 궁금한건 존재하지 않는 가상 IP쪽은 리턴된는 시간이 2-3분이 걸립니다.
이시간은 리턴값을 확인하는데 치명적이라 하겠습니다.
존재하지 않는 가상IP쪽도 존재하지않는 고정IP쪽처럼 바로 리턴값을 확인 할수 잇는 방법을 알고 싶습니다.
제가 할려는 긍극적인 것은 고정 IP나 가상 IP나 연결이 가능한 상태인지를 확인 하는것입니다.
그래서 현재는 connect() 리턴값으로 확인하고 있는거구요
그럼 답변을 부탁드립니다.
[quote]고정IP와 가상 IP에 대한 connect() 리턴값이 다르
TCP connect 가 실패하는 경우는 여러 가지로 들 수 있습니다.
먼저, 존재하지 않는 IP로의 접속 시도는 보통 클라이언트의 타이머에 의해 감지됩니다. 즉, 타이머가 만료될 때까지 어떤 기준을 두어 TCP 접속
요청(SYN)을 보내보다가 몇 번을 시도해도 응답이 없으면 결국 포기하게
되는 방식입니다.
여기서 타이머의 제한 시간이나 TCP 자체적인 SYN 재전송은 커널에서 다루기 때문에
제가 알기로는 애플리케이션에서 제어할 수 있는 방법이 없습니다.
(커널 파라미터를 수정할 수 있는 유닉스도 있는 걸로 알고 있습니다.)
따라서, 리눅스에서 몇 분이나 걸리게 되는 것이죠.. 윈도우즈의 경우는
이보다 훨씬 더 짧습니다(납득할 만한 수준임.. 갠적으로는 리눅스의 경우,
지나치게 길다고 생각합니다.)
그리고 두 번째, connect 실패 케이스는 상대방 혹은 네트워크 어딘가에서 연결이
될 수 없다는 것을 "명시적"으로 알려 오는 경우입니다.
이건 다시 여러 경우를 들 수 있는데요..
먼저, 흔히 접하게 되는 port unreachable의 경우는 상대방 호스트에 도달은 했으나
시스템에 해당 서버 포트가 열려(listening) 있지 않은 경우입니다. 이 경우
상대방의 TCP는 곧바로 RST(connection 강제 끊기)를 날리게 됩니다.
또, 이야기하신 network unreachable의 경우는 해당 호스트가 존재하는
네트워크로 도달할 수 없다는 것을 나타냅니다. 이 에러는 상대방 호스트가
아니라 중간 시스템(라우터, 게이트웨이, 방화벽 등등)에서 보내게 됩니다.
예를 들어, 위의 경우 방화벽에서 목표 시스템으로의 접속을 차단함과 동시에
ICMP network unreachable error 를 보내게 되면, 클라이언트는 접속이
불가능함을 즉시 인식하고 에러를 떨어뜨리겠지요..
이 외에도 "명시적"으로 connection이 실패하는 경우는 몇 가지가 더 있습니다만,
어쨌든, "명시적"인 에러는 에러가 발견된 즉시 connect() 시도가 실패합니다.
그래서 질문하신 것과 같은 현상이 생기는 것이죠..
앞서 말한대로 커널 파라미터니.. 뭐 이런 걸 건드리는 것보단
non-blocking connect 를 이용하실 것을 권합니다.
간단히 설명하면,
1) fcntl() 을 이용하여 socket을 non-blocking으로 설정한다.
2) connect()를 수행한다.
- 이 경우 connect() 는 블록되지 않고, 곧바로 리턴합니다. 이 때, connect 수행 자체에 문제가 없었다면 errno에 EINPROGRESS 값이 설정됩니다. 명령이 "진행 중"이므로 기다리라는 뜻이죠..
3) 이제 select()를 이용하여 위의 socket에서 응답이 오기를 기다립니다.
단, 이 때 select()에 원하는 만큼의 timeout을 인자로 지정합니다. 즉,
예를 들어 3초(이 정도면 정말 충분합니다!!)로 제한 시간을 걸어서 그 안에
응답이 올 때만!! connect가 성공했다고 가정하고 그렇지 않으면, 자체적인
판단으로 실패했다고 보면 됩니다.
자세한 부분은 non-blocking socket connect에 대한 자료를 찾아 보세요 ^^
댓글 달기