위의 소스 /*여기*/ 에서 close되었는지 여부를 알수 있는 방법은 없을까요?
답변중에 fctl,setsockopt를 사용하면 된다고 하셔서.지금 보고 있는데요..
예제가 없더서.... 그런데..제가 보고 있는 자료중에
이것을 사용할 려면 , listen() 호출전에 사용하라고 언급되어 있더군요.
그러면..이후 동작하는 모든 read,write가 non-blocking으로 되는것 아닌가요?
그러면 안 되는데요.. read에서는 blocking이 되어야 하는데..
제가 잘 못 알고 있는것인지..그냥 사용하면 되는데..괜한 우려인가요??
/**/여기2 에서는 close(sok_num)하면 return 값이 ==>0 : 정상종료
그런데 여기1 에서 close(sok_num)하면(물론 여기1 에서 close 안 했구요) return 값이 -1 : 에러로 나오는 현상은 무엇때문일까요???
일단 경험적으로 제가 아는 것이..
소켓에서 recv했을 때 정상적으로 받은 것으로 나오고 받은 길이가 0이면 보통 연결이 (정상) 종료된 경우더군요.(이부분은 제가 틀렸으면 지적해주세요. 윈도에선 확실히 그랬던 것 같고...)
select는 리눅스 기초 프로그래밍 책에 잘 나와있을 것 같네요 소켓 통신쪽에..
select문에 read, write, error FD체크 부분이 있잖아요 거기에 알맞은 소켓을 넣어두고(이부분은 책 찾아보세욥. 아니면 kldp에 한글로 소켓 프로그래밍 부분이 있습니다. (Beej의 소켓 프로그래밍 하우투였나..))
또한 timeout값도 넣어두세요. 1초, 0.2초 맘대로...
그리고 while 문으로 루프 돌립니다. (아 물론 while이 아니어도 루프를 돌리실 수 있습니다 쩝..)
select의 리턴값이 0이 아니면 에러이거나 타임아웃이고
read,write, error 셋중 어떤 이벤트가 떠서 select문에서 빠져나왔는지 체크하시고 (FD_SET(read_fd)였나..)
read였다면 읽어보시고 길이도 체크해보시고, error였다면 에러체크 해보시고 연결 끊으시고요.. 이렇게 받는 쓰레드or 프로세스에서 처리하시면 될 것 같네요.
제 생각에도 전에 질문 하셨던분 같네요. 혹시 제게 이메일 보내주셨던분 맞나요.? 제가 답장 할려고 해도 편지가 되돌아 와서 편지를 못보내 드렸습니다. 하여간 여기서 다시 뵈니 반갑습니다.
서버쪽에서 클라이언트의 통신 상태를 체크 하기에는 SELECT가 "와따" 입니다. 먼저 SELECT를 사용하기 이전에 NON-BLOCK 모드로 들어 가시고 SELECT를 사용하시고 RECV쪽에서 감지 하시면 됩니다. 즉, RECV는 정상 리턴일때 읽은 바이트 만큼 리턴을 하지만 RECV() <= 0 일 경우에는 모두 에러입니다. 이중 중요 한것은 0 인데 바로 이부분이 접속이 정상적으로 끊어진것입니다.
그리고 한가지 주의 하실점은 TCP/IP통신에서는 전달은 보증이 되지만 언제 전달이 될지는 보증이 되지 않습니다. 따라서 세가지 부분을 만들어 놓으셔야만 되는데
1. SELECT에서 NON-BLOCK 모드로 통신 하게 설정 fcntl 등...
2. 원하는 시간 만큼 타임아웃을 SELECT에 설정
3. recv에서 내가 읽을 바이트수 만큼 읽고서 리턴하게 설정(while 등으로)
이정도 입니다.
쓰레드나 PORK는 제가 사용하지 않아서 그쪽은 잘 모르겠습니다.
lol
shean0 wrote:
지금 폰과 통신하는프로그램을 작성중인데요..
서버에서 close하기전에 "폰쪽에서는 "close되었다구 하는데요..
서버에서 소켓넘버를 가지고 체크하는 방법이 없을까요??
아니면..다른 방법이라두..일단 accept된 소켓 번호를 int값을 가지고 있구.
close(sock_num); 하면.
.. sock_num==>NULL 일 것이라 생각했는데..
아니더군요..
fcntl ()이나 setsockopt ()등으로 해당 소켓을 NONBL
fcntl ()이나 setsockopt ()등으로 해당 소켓을 NONBLOCK으로
만든후에 recv ()를 해 보면 될것 같네요..
꼭 NONBLOCK뿐아니라 소켓옵션에 recv 타임아웃을 설정해도 될테고..
recv ()의 리턴값이 -1이면 close 된것이고 0이면 살아있지만 타임아웃
걸린거고, 0 이상이면 데이터를 수신한게 되겠죠..
가끔은 밥을 굶어도 살 수 있다.
그냥 읽다가 에러날때, 처리 하면 되지 않을지요...
sockfd값은 그냥 int값일뿐, 그걸로는 close여부를 알수 없지요.
그걸로 어떤 작업을 하다가 에러 나면 리턴값과 에러코드 보구 처리하곤 합니다.
보통 주된 close위치는, 읽다가 에러날 때 소켓을 닫는데요..
(non-block일땐 errno이 EAGAIN등이 아닐때 close)
제가 질문의 의도에 맞춰 제대로 답변을 하는건지 아리송 하네요.. :-P
non-blocking 하면요..
예를 들면 이런 소켓 소스에서요
위의 소스 /*여기*/ 에서 close되었는지 여부를 알수 있는 방법은 없을까요?
답변중에 fctl,setsockopt를 사용하면 된다고 하셔서.지금 보고 있는데요..
예제가 없더서.... 그런데..제가 보고 있는 자료중에
이것을 사용할 려면 , listen() 호출전에 사용하라고 언급되어 있더군요.
그러면..이후 동작하는 모든 read,write가 non-blocking으로 되는것 아닌가요?
그러면 안 되는데요.. read에서는 blocking이 되어야 하는데..
제가 잘 못 알고 있는것인지..그냥 사용하면 되는데..괜한 우려인가요??
/**/여기2 에서는 close(sok_num)하면 return 값이 ==>0 : 정상종료
그런데 여기1 에서 close(sok_num)하면(물론 여기1 에서 close 안 했구요) return 값이 -1 : 에러로 나오는 현상은 무엇때문일까요???
언제나 즐프를 꿈꾸며~
음.
select() 함수라는 함수가 있죠. 해당 소켓에 쓰기가 가능한지, 읽기가 가능한지, 에러인지 아닌지를 감시해주는 함수인데.. 쓰일만할지?
저번에 질문 하셨던 분 같은데.. 음.역시나 아직 회사가 아닌관계
저번에 질문 하셨던 분 같은데.. 음.
역시나 아직 회사가 아닌관계로 자세한 설명은 불가능하군요..
일단 이렇게 하면 알아보실 수 있을겁니다.
저는 쓰레드를 돌려서 소켓에서 받는 작업을 했는데요.
select를 쓰시면 질문하신 구현이 될 것입니다.
일단 경험적으로 제가 아는 것이..
소켓에서 recv했을 때 정상적으로 받은 것으로 나오고 받은 길이가 0이면 보통 연결이 (정상) 종료된 경우더군요.(이부분은 제가 틀렸으면 지적해주세요. 윈도에선 확실히 그랬던 것 같고...)
select는 리눅스 기초 프로그래밍 책에 잘 나와있을 것 같네요 소켓 통신쪽에..
select문에 read, write, error FD체크 부분이 있잖아요 거기에 알맞은 소켓을 넣어두고(이부분은 책 찾아보세욥. 아니면 kldp에 한글로 소켓 프로그래밍 부분이 있습니다. (Beej의 소켓 프로그래밍 하우투였나..))
또한 timeout값도 넣어두세요. 1초, 0.2초 맘대로...
그리고 while 문으로 루프 돌립니다. (아 물론 while이 아니어도 루프를 돌리실 수 있습니다 쩝..)
select의 리턴값이 0이 아니면 에러이거나 타임아웃이고
read,write, error 셋중 어떤 이벤트가 떠서 select문에서 빠져나왔는지 체크하시고 (FD_SET(read_fd)였나..)
read였다면 읽어보시고 길이도 체크해보시고, error였다면 에러체크 해보시고 연결 끊으시고요.. 이렇게 받는 쓰레드or 프로세스에서 처리하시면 될 것 같네요.
rommance.net
Re: 열려져 있던 소켓이 "close"되었는지..아닌지 알
제 생각에도 전에 질문 하셨던분 같네요. 혹시 제게 이메일 보내주셨던분 맞나요.? 제가 답장 할려고 해도 편지가 되돌아 와서 편지를 못보내 드렸습니다. 하여간 여기서 다시 뵈니 반갑습니다.
서버쪽에서 클라이언트의 통신 상태를 체크 하기에는 SELECT가 "와따" 입니다. 먼저 SELECT를 사용하기 이전에 NON-BLOCK 모드로 들어 가시고 SELECT를 사용하시고 RECV쪽에서 감지 하시면 됩니다. 즉, RECV는 정상 리턴일때 읽은 바이트 만큼 리턴을 하지만 RECV() <= 0 일 경우에는 모두 에러입니다. 이중 중요 한것은 0 인데 바로 이부분이 접속이 정상적으로 끊어진것입니다.
그리고 한가지 주의 하실점은 TCP/IP통신에서는 전달은 보증이 되지만 언제 전달이 될지는 보증이 되지 않습니다. 따라서 세가지 부분을 만들어 놓으셔야만 되는데
1. SELECT에서 NON-BLOCK 모드로 통신 하게 설정 fcntl 등...
2. 원하는 시간 만큼 타임아웃을 SELECT에 설정
3. recv에서 내가 읽을 바이트수 만큼 읽고서 리턴하게 설정(while 등으로)
이정도 입니다.
쓰레드나 PORK는 제가 사용하지 않아서 그쪽은 잘 모르겠습니다.
lol
제 예제 코드입니다
제 프로젝트에서 쓰던 거라 바로 적용되시진 않을 지 모르지만 제 코드를 주석 달아서 올립니다.
말씀 드렸다시피 저는 쓰레드로 돌렸습니다.
또 받는 메시지의 길이가 정해져있을 때는
이렇게 MSG_WAITALL로 받으시고 리탄값이 -1일때 연결 에러로 처리하시면 비정상적인 종료를 처리하실 수 있습니다.
그런데 써놓고 보니 가물가물 한 것이.. 어제 쓴 것 처럼 recv의 리턴값이 0이면 연결 종료 된 것인지 기억이 안나네요.. 혹시 아시는 분 답변좀 해주세요..
맨페이지에는 WAITALL의 경우는 연결이 끊어져도 리턴하네요. 아마 이때는 길이가 예상했던 것보다 짧을테니 길이체크도 하셔야 되겠습니다.
rommance.net
댓글 달기