소켓 프로그램 질문 입니다.
좋은 하루 되세요.
Microwindows-0.92 환경에서 서버 프로그램을 만들어 보고 있습니다.
질문은 클라이언트가 서버에 접속해 있다가 접속을 종료하면 서버에서 처리를 어떻게 하느냐 하는겁니다.
정확히 말하면 클라이언트 접속 종료를 어떻게 서버가 알 수 있냐는 거죠..
두번째는 접속을 기다리는 부분은 쓰레드로 작성하고 접속된 클라이언트에서 데이타를 받기 위해
클라이언트 마다 쓰레드를 생성해서 데이타를 감시하고 받습니다. 그런데 그렇게 하니까 프로그램이 현저히
느려지네요. 쓰레드를 모두 종료 후 에도 똑같이 느린데요 뭐가 잘못된건지 고수님들 조언 부탁드립니다.
아래는 클라이언트 접속을 기다리고 접속 처리를 해 주는 쓰레드 함수 입니다.
void *thread_waitclient(void *arg)
67 {
68 char *str;
69
70 // open socket
71 if((svr_sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
72 {
73 printf("server : socket open failed\n");
74 return ;
75 }
76
77 bzero((char *)&svr_addr, sizeof(svr_addr));
78 svr_addr.sin_family = AF_INET;
79 svr_addr.sin_addr.s_addr = htonl(INADDR_ANY);
80 svr_addr.sin_port = htons(1000);
81
82 if(bind(svr_sock, (struct sockaddr *)&svr_addr, sizeof(svr_addr)) < 0)
83 {
84 printf("server : bind failed\n");
85 return ;
86 }
93 printf("listen client connection request ...\n");
94
95 // wait connection
96 for(;;)
97 {
98 listen(svr_sock, 1);
99 if(con_cnt > 4) return;
100 st_clt.clilen = sizeof(st_clt.clt_addr);
101 // accept
102 if ((st_clt.clt_sock = accept(svr_sock, (struct sockaddr *)&st_clt.clt_addr, &st_clt.clilen)) == -1) {
103 printf("server : connection failed\n");
104 return;
105 }
106 else {
107 // get client IP, get connect time
108 getpeername(st_clt.clt_sock, (struct sockaddr *)&st_clt.clt_addr, &st_clt.clilen);
109 strcpy(st_clt.clt_ip, inet_ntoa(st_clt.clt_addr.sin_addr));
110 printf("client ip : %s\n", st_clt.clt_ip);
111 memcpy(&st_clt.con_time, ¤t, sizeof(TOCTIME));
112 // make thread for receive
113 add_tail(st_clt);
114 if((pthread_create(&t_id[con_cnt+1], NULL, thread_revdata, NULL)) != 0)
115 {
116 printf("Create thread[%d+1] failed\n", con_cnt);
117 return ;
118 }
119 con_cnt++; tot_clt++;
126 }
127
128 return;
129 }
void *thread_revdata(void *arg)
132 {
133 int i, rev_cnt;
134 int nRev_byte, nIndex=0;
135 char szData[MAXCHAR], str[80];
136
137 node *p_cur;
138 // if arrived data then receive data
139 while(1)
140 {
141 p_cur = head->next;
142 while(p_cur != tail)
143 {
144 ioctl(p_cur->clt.clt_sock, FIONREAD, &rev_cnt);
145
148 memset(szData, 0, sizeof(szData));
.....
151 nRev_byte = recv(p_cur->clt.clt_sock, &szData[nIndex], 1, 0)) < 0)
.....
177 p_cur = p_cur->next;
178 } //while
179 }
180 }
TCP/IP에서 접속을
TCP/IP에서 접속을 하게 되는 경우엔, Three-way Handshake방식을 사용하기 때문에
Syn, Ack, Syn의 교환을 이용하여 클라이언트가 접속이 끊겼는지 아닌지 자동으로 확인하게 됩니다.
서버쪽은 물론 클라이언트에서역시 3-way 핸드쉐이킹이 이루어 지기 때문에
자연스레 접속종료를 알아챈다고 알고 있습니다..........만? ㅡ,.ㅡ:::
내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.
내 마음속의 악마가 자꾸만 나를 부추겨.
늘 해왔던 것에 만족하지 말고 뭔가 불가능해 보이는 것을 하라고 말야.
클라이언트 종료
접속 종료를 알아 채는데 어떻게 처리를 하죠...
클라이언트가 강제 종료되서 접속이 끊어졌다고 가정할 때 서버에서 클라이언
트 종료 메시지를 뿌리고 싶다면 어떻게 하는지요.
윈도우에서 CAsyncsocket을 사용한 경우 접속된 쪽이 close되면 메시지가
발생하죠.. 버클리 소켓에서는 뭐가 생기는지.. 그런걸 모르겠네요
혹시 예제라도 있으신지요...
원격지가 단절된것을
원격지가 단절된것을 블록킹모드인 경우, 유닉스 BSD소켓에서는 write()시 SIGPIPE 시그널 검사와 READ()에서 0이 리턴되는 것으로 압니다.
그리고, fcntl()로 검사하면 bad file no 에러로 검출하기도 합니다.
man read
man write
해서 소켓인 경우, 부분에 대해 정독해보세요.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
------------------ P.S. --------------
지식은 오픈해서 검증받아야 산지식이된다고 동네 아저씨가 그러더라.
댓글 달기