LISTEN PORT가 close()가 안됩니다.
TCP Server와 Client역활을 모두 하는 데몬 프로그램을 짜고 있습니다.
a) Daemon Main_port1 Sub_port1 ...
b) Daemon Main_port2 Sub_port2 ...
데몬 프로그램이 위와 같이 쌍으로 실행되어서
하나는 다른 하나의 백업 역할을 합니다.
클라이언트들이 a)와 b)로 접속하여 데이터를 넘기면
a)와 b)는 데이터를 다시 또다른 데몬으로 넘겨서
그 결과 값을 클라이언트로 보내 send합니다.
a)와 b)는 항상 같이 떠있지만 하나는 다른 하나의 백업 역할을 합니다.
다시 설명하면 클라이언트들이 a)로 데이터를 send하다
a)에 문제가 생겼을 때 클라이언트에서 자동으로 b)로 데이터를 send합니다.
클라이언트에서 a)로 send하다가 b)로 접속을 바꿀 때,
b)로 connect를 요청할 때 b)에서는 accept가 발생되어
a)를 kill합니다.
그리고 약 1분 정도 후에 다시 a)를 실행시킵니다.
이때 accept부분을 select로 처리를 하는데,
select에서 EINTR가 발생하여
if (errno == EINTR)continue;
이런식으로 처리를 하였습니다.
while(1) { FD_SET(sock, &read_fds); if(select(nfds, &read_fds, (fd_set *)0, (fd_set *)0, (struct timeval *)0) < 0) if (errno == EINTR)continue; else sprintf(msgbuf, "select error: %s", strerror(errno)); if(FD_ISSET(sock, &read_fds)) { len = sizeof(peeraddr_in); bzero((char *)&peeraddr_in, len); asock = accept(sock, (struct sockaddr *)&peeraddr_in, &cli_size); kill_daemon(); ====>> accept가 들어오면 상대편 데몬을 kill시킨후 다시 실행 한다.:shock:
이렇게 하면,
a)에서 b) 전환이 문제 없이 잘됩니다.
데이터도 잘받고요.
그런데 문제는 a)를 다시 실행 시킬때 그전의 a)가 사용하던
Port가 계속 LISTEN 상태로 남아있어 a)를 실행시킬 수가 없습니다.
ps로 확인해 보면 a)는 분명히 kill된게 분명한데
netstat 으로는 계속해서 남아있습니다.
b)와 a)가 서로 kill을 하면서 어떤 연관이 있어서
port가 close가 안되는 것 같습니다.
b)에서 a)를 kill하기 전에 signal을 보내 a)는 kill당하기 전에
listen 소켓을 close()하는 데도 마찬가지 이네요...ㅠㅠ;
수동으로 b)를 kill하면 그전의 a) port와 b) port가 모두 close()됩니다.
지금 사용하는 서버는 다음과 같습니다.
$ uname -a
AIX hostname 2 5 00CF5FFC4C00
이곳 게시판을 찾아보니 열려있는 포트의 pid를 알수있는 명령어로
lsof을 사용하면 알 수 있다고 그러는데 안탑깝게도 안깔려 있네요...
이런일이 발생하는 원인과 lsof말고 다른 걸로 open된 port의 pid를 알 수 있는 방법이 있나요...??
고수님들의 답변 부탁드립니다....
* 질문자의 "close가 안된..."(<=표현이 정확하지 않음)
* 질문자의 "close가 안된..."(<=표현이 정확하지 않음) 원인(이유가 궁금하다?)은 TCP 프로토콜 유한상태머신(FSM)에서 TIME_WAIT가 도대체 뭔지를 검색해 보시고,...
* 증상을 해결하려면(코딩으로 어떻게 해결하나?),
setsockopt()함수로 SO_REUSEADDR 을 사용하세요.
* KLDP내에서만도 TIME_WAIT, setsockopt, SO_REUSEADDR등으로 검색하면 무진장 나올겁니다. 결과가...
* ps로 확인을 하면 프로세스는 kill 된 상태이고요. clos
* ps로 확인을 하면 프로세스는 kill 된 상태이고요.
close는 일어나지가 안네요.
다시 말씀드리면 kill된 프로세스가 사용하던 포트가 LISTEN 상태로 남아있습니다.
물론 TIME_WAIT는 없습니다. ㅡㅡ;;
* 물론 TCP 서버이고 데몬으로 실행되어야하기 때문에
setsockopt()함수로 SO_REUSEADDR 을 사용했습니다.
* KLDP안에서 무진장 찾아봤습니다....ㅠㅠ
비사용중인 포트를 확인하시고, 비사용중인 포트로 변경해서(포트변경) 서버
비사용중인 포트를 확인하시고, 비사용중인 포트로 변경해서(포트변경) 서버를 실행해 보시고 다시 죽여보세요. 그리고, 확실하게 해당 서버가 죽었는지를 다시 검토해 보시지요.
혹시, 다른 프로세스(죽은 프로세스말고)가 포트를 열고 있는것은 아닌가?하는 기초적인 단순짐작을 해봅니다.
BIND가 실패한다는 말씀이신가요...?저는 주로...1. k
BIND가 실패한다는 말씀이신가요...?
저는 주로...
1. kill했을때 죽는 프로세스가 시그널을 핸들링하여 소켓을 모두 닫고 죽게 한다. (당연히 9시그널로 죽이면 안되겠죠?)
2. bind하는 쪽에서는 실패할 경우 어느정도 간격을 두고 재시도하도록 한다.
이렇게 합니다.
----------------------------------------------
한번뿐인 인생....
미친듯이 살아보자!
----------------------------------------------
접속해있는 socket을 양쪽 모두 닫지 않으면 프로세스가 죽어도 얼마기
접속해있는 socket을 양쪽 모두 닫지 않으면 프로세스가 죽어도 얼마기간동안은 포트가 닫혀지지 않습니다.
kill 하기전의 코드를 한번 확인해보세요
흠 저도 예전 제가 경험했던 거라 그냥 혹시 이런건 아닐까하고 단순짐작만 해봅니다.
Chaos to Cosmos,
Chaos to Chaos,
Cosmos to Cosmos,
Cosmos to Chaos.
[quote="ctcquatre"]접속해있는 socket을 양쪽 모두 닫
* 이것을 TIME_WAIT상태라고 합니다.
해결방법은 다양한데, setsockopt()로 보통 합니다(윗글참고)
---------------------------------------------
* 질문자님 어떻게 되었는지 궁금합니다. 해결되었는지? 아닌지? 해결되었다면, 원인도 공유해 주시면 감사하겠습니다.
우선 답변주신분들께 감사드립니다...^^lsof를 구해서 설치해서
우선 답변주신분들께 감사드립니다...^^
lsof를 구해서 설치해서 보니,
port를 잡고 있는 프로그램이 어떤건지 쉽게 알 수가 있었습니다.
이상하게도 b)란 놈이 Listen port를 두개 다 잡고 있더군요..ㅠㅠ;
다시 간단하게 어떤 방식으로 구현을 해야 되는지 설명을 드리겠습니다.
동일한 데몬이 2개가 포트만 다르게 실행이 됩니다.
a) AAA 1000 1001 [...]
b) AAA 1001 1000 [...]
AAA는 실행데몬명이고 뒤의 1000, 1001은 포트명입니다.
AAA가 실행될 때 자신의 정보를 저장을 하기 때문에
a)는 데몬명이 자신(AAA)와 같고 뒤의 포트(1001)으로 실행된
데몬이 자신의 standby 데몬인것을 알 수 있습니다.
두 데몬이 실행은 각각 1000[a)]과 1001[b)]을 LISTEN PORT로 실행됩니다.
그리고 클라이언트에서 정보를 a)-1000으로 보내다 a)에 이상이 있으면
자동으로 b)-1001으로 보내게 됩니다.
이때 b)는 accept에서 클라이언트가 들어왔다는 것을 감지할 수 있겠지요.
이때 b)는 a)에 이상이 있다고 판단을 하여 a)를 kill시키고
잠시후(1분 정도)에 restart (AAA 1000 1001 [...]) 시키면 되는 거였습니다.
그런데 이상하게도 a)에서 메시지를 받다가 이상이 생겨,
b)에서 a)를 kill한 후에 다시 살리려면
말씀드린데로 PORT가 LISTEN 상태이고
lsof로 보면 a)가 사용하던 포트(1000)가 b)에 물려있어서
1000포트를 사용할 수 없었던 것입니다....ㅠㅠ
b)에 1000번과 1001번 모두 물려 있더군요....
그래서 a)를 kill, restart 시켜줄때 fork도 사용을 해보고
간단한 scpript를 만들어 pid를 넘겨 주는식으로 해도 마찬가입니다.
그래서 kill을 b)가 직접하지 않고 b)는 a)를 kill해야 된다는 정보를
다른 프로그램에 알려줘서 kill과 restart를 다른프로그램 c)에서 하고 있습니다. ㅠㅠ
==> b)가 a)를 kill하고 restart 시킬 때 system(), exec()계열을 사용했었습니다.
해결은 못하고 다른 방법으로...^^;;
혹시 해결방법이 있나요...??
댓글 달기