네트워크 프로그래밍에 대해 질문. client 쪽에 connection refu
글쓴이: mon12key / 작성시간: 수, 2003/07/23 - 9:39오전
TCP를 사용한 네트워크 프로그램으로, client와 server 사이의 중계 역활을 하는 프로그램을 작성하려 합니다. 이하 중개기라 부르겠습니다.
이 중계기는 clinet-server 입장에서는 단순히 proxy역활만 하는 것 처럼 보이게 하고 싶습니다.
client에서 연결 요청(connect())를 하게 되면 중계기에서는 요청을 listen()하고 있다고, 적절한 server가 있으면 중계기에서 accpet()를 하고, 적절한 server가 없으면 clinet쪽에 connection refuse 에러가 나도록 만들려 합니다.
그런데, connection refuse는 아예 listen 하고 있는 port가 없을때 나오는 에러 메세지여서, 이경우 중개기가 listen하고 있는 관계로 문제가 생깁니다.
Forums:
질문의 요지가 무엇인지 잘 모르겠습니다만..[quote="mon1
질문의 요지가 무엇인지 잘 모르겠습니다만..
client -- proxy -- server 이런 의미겠군요.
1. client's ---> proxy (listen)
2. proxy --> server(적절한?..) 선택
3. client <---- ((proxy)) ----> server (proxy는 passing만)
이런 의미로 들리구요..
이건.. 무슨의미죠? 지금 외근나가야 하니까 나중에 좀더 자세한 설명이 추가되어 있기를 바랍니다.
역활 : 역할의 잘못중개 : 중개(仲介)ꃃ제삼자로
역활 : 역할의 잘못
중개 : 중개(仲介)
ꃃ제삼자로서 두 당사자 사이에 서서 일을 주선함. ¶중개 수수료/부동산 중개/그렇게 비축된 물건을 조합에서 사들여 팔거나 중개 또는 위탁 판매를 할 경우….≪이문구, 으악새 우는 사연≫ꄘ거간03(居間)①.ꄘ거매02(居媒).
중계 : 중계(中繼)[-계/-게]
ꃃ①중간에서 이어 줌. ¶산간 지대에서는 사단과 대대, 대대와 중대 사이의 교신이 잘 안되니까 중계 역할을 하는 곳이 필요하다. ②〖언론〗=중계방송①. ¶라디오 중계/텔레비전 중계. ③〖언론〗=중계방송②. ¶스포츠 중계/현장 중계.
^^;; 중개 -> 중계로 수정하였습니다.논리적으로 글쓰기가 쉽
^^;; 중개 -> 중계로 수정하였습니다.
논리적으로 글쓰기가 쉽지 않군요. 죄송합니다.
글쓰기 공부를 해야겠습니다. ^^;
우선 제가 만든 중계기(proxy 비스무리...) 는 listen()상태입니다.
이 중계기의 port로 client가 접속하였을때, 적절한 서비스가 있을때만
client로 접속을 허락하고 싶습니다.
현재 적절한 서비스가 있을때는 client에 적절한 서비스를 forward시키는데,
서비스가 없을때 client가 연결이 바로 안 끊기고 기다리고 있습니다.
listen하고 있는 소켓을 close()시키면 연결이 바로 끊기는데 이 방법 말고,
다른 방법으로 client쪽에 연결을 끊는 방법이 없을까요? client쪽에서는
"connect refuse" 에러 메세지가 나오도록.....
[quote="mon12key"]listen하고 있는 소켓을 close(
proxy쪽에서 client의 sockfd를 복사해서 가지고 있어야 겠군요..
proxy에서 연결은 계속 물고 있어야 할 겁니다. 대신 타임아웃을 걸어서 일정 시간이 지나면 연결은 끊어야 겠죠.
그리고 주기적으로 검사해서 해당 server가 active되었을 때, forwarding 해주는 방식이 있겠군요.
proxy 샘플을 하나 만들어 보고 다시 올려드리죠.
음... 꼭 connection refuse가 나와야 되나요? 그럴 이유
음... 꼭 connection refuse가 나와야 되나요? 그럴 이유가?
아무튼 이것이 좋은 방법은 아니지만 일단 설명해보겠습니다.
listen한 상태로 일단 있습니다.
accept전에 select ( RxD ) 를 걸어둡니다.
select가 걸리면 accept로 곧바로 가지 말고
서버쪽에 연결시도를 합니다.
연결이 되지 않으면 해당 listen소켓을 닫았다가 엽니다.
연결되면 accept를 하게 되면 되지 않을까라는
생각을 해봅니다.
해보지 않아서 잘 모르겠지만 그냥 추측이니까
믿지는 마세요.
프락시 샘플은 쉽게 찾으실수 있을겁니다. http//proxy.sou
프락시 샘플은 쉽게 찾으실수 있을겁니다.
http//proxy.sourceforge.net
이것은 아주 간단한 샘풀이니 한번 참조해보세요.
접속 실패의 경우만..
1. 클라이언트 접속
2. 프락시에서 accept
3. 서버쪽에 접속(select timeout with non-block IO)
4. 서버쪽에 접속 실패(back to block IO/클라이언트 접속 해제)
구성할수있는 경우는 상당히 다양합니다. 아주 일반적인 서버 구성일수도 있습니다. 여기서 조금(상당히) 발전하면 미들웨어일수도 있구요. 너무 어렵게 생각하지 마시고 한번 시도해보시는게 어떨까요.?
다만 connection refuse를 클라이언트에게 전달해주는것은 다른 방법으로 해서 메시지를 넘겨주는건 어떨까요.? 그리고 서버쪽에 접속하는데 만약 서버가 여러대 라면 이런 방법도 괜찮을것 같습니다.
1. 프락시에서 서버쪽 타임 아웃은 5초(저는 보통 접속 타임아웃을 3초로 해놓았는데 어떤 경우에는 정상인데도 3초 이내에 접속이 안되는 경우가 왕왕 생기드라구요. 현재는 5초인데 이정도면 무사 통과 하는것 같습니다. 접속하는 서버의 갯수는 약 20개 정도이고 프로그램은 5가지 정도 됩니다.)
2. 서버는 5대가 존재.
3. 클라이언트는 접속 타임아웃이 21초
이럴 경우 클라이언트에서 최초 프락시에 접속한후에(이때도 타임아웃이 유효하겠죠) 프락시는 각 서버에 접속을 시도합니다. 5초 이내에 접속이 실패하면 다음 서버로 그리고 다음 서버로.. 그래서 최후 5대 모두 실패하면 클라이언트에게 메시지를 보내줍니다. 그리고 접속을 강제 종료합니다.
이럴 경우 클라이언트가 접속을 종료하는게 아니라 프락시에 접속을 종료 하는것이죠. 클라이언트는 아직 타임아웃이 1초 남아 있기 때문에 기다리는 상황인데 이때 서버쪽에 메시지를 받고(유효한 서버가 없습니다. 어쩌구..) 접속이 해지되는 상황입니다.
이런것은 어떨까요.? 원하시는것을 한번 더 포스팅 해주세요.
즐거운 하루 되세요.
적절한 서버가 없다..port unreachable, networ
적절한 서버가 없다..
port unreachable, network unreachable 등의 예를 말씀하시는 듯 하군요..
예를 들면, 어떤 서버에 도달했는데 포트가 열려 있지 않다던지, 그런 IP로 도달할 수 없다든지요..
저런 처리는 ICMP라는 프로토콜을 통해 이루어집니다. 더 정확히 말하면, ICMP error message들이 처리합니다. 절대 TCP, UDP 자체가 저런 기능을 모두 처리하지는 않습니다.
따라서, 조금 고생할 맘만 있으시다면,(또 꼭 그렇게 하고 싶다면) ICMP를 분석해 보시기 바랍니다.
ICMP 규격에 맞도록 해당 서버에서 포트가 열려 있지 않은 경우, 프록시에서 에러에 해당하는 ICMP 패킷을 만들어서 이를 클라이언트로 보내주면 되겠지요.
ICMP 패킷 만들어 보낼 때는 raw socket을 사용하시면 되구요 ^^
그럼!
connection refuse를 원하신다면
connection refuse는 해당하는 서버에서 접속을 거부했을 경우에
발생할 수 있는 상황입니다. 즉 어떤 서버로 접속을 시도했을때
서버에서 RST flag가 설정된 패킷을 클라이언트로 전송했을 경우에
클라이언트는 바로 접속을 끊게 됩니다.
port unreachable이나 network unreachable은 패킷이 전혀
그쪽 서버로 도달 할 수 없는 상황 (케이블이 연결되어 있지 않다든지)
에서 발생하므로 적절하지 않은것 같습니다.
하지만 위에서 논의 되었다 시피 강제적으로 서버에서 접속을 끊게
하는것보다는 서버로 연결을 실패했다는 메시지를 클라이언트로 전송하여
클라이언트에서 스스로 소켓을 close 시키는것이 더 좋은 방법이라고
생각합니다.
잠깐 짬이 나서요...[code:1]하지만 위에서 논의 되었다 시
잠깐 짬이 나서요...
이런 방법은 어떨까요.? 이벤트의 발생 위치를 생각해보면 클라이언트쪽이니 클라이언트가 접속을 끊겠 하는것이 일반적일것입니다. 그런데 클라이언트가 직접 제작하시는것이 아니라 telnet이나 혹은 http이실수도 있으시니 이럴때는 프락시쪽에서 강제로 접속을 끊어주시는게 어떨까요.? 그것이 아니라 클라이언트도 직접 제작하시는거라면 클라이언트에서 그러한 상황에서 접속을 끊게 하는것이 일반적이실겁니다.
그 반대로 클라이언트쪽에서 접속 해제시 서버쪽 접속을 해제하는것도 마찬가지 일것 같습니다. 또 이런 생각도 해볼수 있을것 같습니다. 그 중계 서버라는것이 만약 async 통신을 지원한다면.. 하는 경우입니다. 이럴 경우에는 이벤트가 발생하는 위치 자체가 별 의미가 없으므로 몇가지 룰을 정의 하셔서 하시면 될것 같습니다. 꼭!! 이렇게 해야 하는것은 절대 아닙니다. 그냥 제가 그런 방식으로 사용하고 있거든요.
쿨럭. -_- proxy open source도 있었군요. -_-
쿨럭. -_- proxy open source도 있었군요. -_-
괜히 이리저리 건드려 봤네요.
혹시 참고가 되실듯 하면 open source로 있는 것보다는 소스양이 작으니까
필요하시다면 메일 주세요. ^^;
[quote]connection refuse는 해당하는 서버에서 접속을
확실히 그렇네요.. 제가 어먼 답변을 해 버렸습니다.
일반적으로 ICMP unreachable error는 중간 라우터에서 전송하는 게 맞습니다.
단, port unreachable error는 end host에서 전송하는 게 맞습니다. 그렇지만 TCP의 경우는 설명해 주신 것처럼 RESET을 이용하여 커넥션을 종료하구요.. UDP의 경우 열려진 포트가 없으면 ICMP port unreachable error를 전송합니다.
흠.. 제대로 확인해 보지 않고 어먼 답변을 해서 혼동하신 분들께 죄송 ㅠㅠ
조언 감사합니다.
리플 다신 분들 모두 감사하고요.
우선 client는 기존 툴을 사용하는 거라 client쪽으로 메세지를
보내 close()시키는 방법은 안되네요.
저는 우선 listen()하는 소켓을 close() 시킨뒤에 다시 열었는데,
client쪽 연결이 끊기지 않고, 다시 연결 시도 하더라구요. ^^;; 멀 잘못했는지
그래서 accept()로 연결하고 바로 close()시키는 방법을 채택했습니다.
근데 아래와 같이 client 쪽에 RST 패킷을 보내면 참 좋을 것 같은데 방법을
찾아 봐야 할 것 같습니다. TCP 레벨이라.. 그런 api가 있을런지 ^^a
답은 이미 나왔습니다.
위에 올려주신 분들 글속에 답이 이미 있습니다만 간단한 pseudo code를
작성해보겠습니다.
이런식으로 작성하면 클라이언트에서는 connect 시도를 했을때
바로 에러를 리턴하게 되므로 신경쓸 필요가 없습니다.
댓글 달기