socket State 알아내기....

jiheony의 이미지

socket state 를 정확하게 알고 싶습니다.

보통 윈도우에서 사용하는 winsock 컨트롤을 보면...소켓 상태가 0~9까지로 정해져 있습니다.
각각의 상태에따라서 속성처럼 스스로 상태를 체크하지요...
즉 처음 생성된 상태 (closed) = 0
접속 대기 = 2
연결 상태(connect) =7
강제 종료 또는 비정상 종료된 상태 = 8~9
뭐...이렇게 해서 상태를 알 수 있느데요...

리눅스에서 inet 소켓을 사용하여 서버/클라이언트 환경을 꾸밀때...
윈도우 처럼 상태를 알 수 있나요?
제가 원하는건 프로그램이 예기치 않은 상황에서 갑작스럽게 종료되거나 리셋되어 소켓연결이 깨졌을때 (윈속에서는 8,9 번 상태이겠지요..) 이것을 closed 시키고 (0번 상태) 싶거든요...

전 select 로 다중 접속 서버 구현중에 있습니다.
고수님들 도와주세요..TT

bugiii의 이미지

select 로 해당 fd 의 에러상태를 알 수 없다는 말씀인가요?

jiheony의 이미지

제가 잘 몰라서...물어보는거에요..
fd 에서 체크하는 방법을 물어보는겁니다. 가장 효율적인 방식에 대해서요..

leilei의 이미지

어느 특정한 때에 소켓의 상태를 알아야 필요가 있나요..?
소켓이 쓰거나 읽거나 혹은 먼가 이벤트를 대기 하거나 한다면..
변화가 있다면 바로 알 수 있습니다.. :)

jiheony의 이미지

이런 상황에서는 어떻게 해야 하나요?
그러니까....지금은 while 문 돌면서 체크를 해야하는 상황인데 어떻게 하면 각 소켓들의 상태를 알 수 있는지...

        while(1)
        {
                allfds = readfds;

                fd_num = select(maxfd+1, &allfds, (fd_set *)0, (fd_set *)0, NULL);

                //만약 소켓 파일지시자에 연결이(read) 이 들어오면
                //accept 해준다.
                if(FD_ISSET(server_sockfd, &allfds))
                {
                        client_len = sizeof(clientaddr);
                        //accept
                        client_sockfd = accept(server_sockfd, (struct sockaddr *)&clientaddr, &client_len);

                        //client 매열에 현재 연결된 client_sockfd 를 입력
                        for(i=0 ; i<FD_SETSIZE; i++)
                        {
                                if(client[i]<0)
                                {
                                        client[i]=client_sockfd;
                                        printf("%d : %d\n", i, client_sockfd);
                                        break;
                                }
                        }

                        //FD_SETSIZE 를 초과해서 client가 접근할 경우 연결을 종료한다.
                        if(i==FD_SETSIZE)
                        {
                                close(sockfd);
                                client[i]=-1;
                        }

                        //fd_set 에 등록
                        FD_SET(client_sockfd, &readfds);

                        if(client_sockfd>maxfd)
                                maxfd = client_sockfd;

                        if(i>maxi)
                                maxi=i;
                        if(--fd_num <= 0)
                                continue;
                }
                //client 배열에 입력된 fd 중
                //연결된(-1이 아닌) fd 에 대해서
                //읽을 데이타가 있는지 검사한 후
                //있으면 처리한다.
                for(i=0; i<=maxi; i++)
                {
                        if((sockfd = client[i])<0)
                        {
                                continue;
                        }

                        printf("maxi %d\n", maxi);
                        if (FD_ISSET(sockfd, &allfds))
                        {
                                //파일 stream pointer 를 첨으로 돌린다.
                        //        rewind(fp);
                        //        memset(buf, 0x00, 255)<=0)
                                if (read(sockfd, buff, 255) <=0)
                                {
                                        close(sockfd);
                                        FD_CLR(sockfd, &readfds);
                                        client[i]=-1;
                                }
                                else
                                {
                                        //client가 quit를 입력하면
                                        //연결을 종료한다.
					
                                        if(strncmp(buff, "quit",4)==0)
                                        {
                                                write(sockfd, "bye bye", 8);
                                                close(sockfd);
                                                FD_CLR(sockfd, &readfds);
                                                client[i] = -1;
                                                break;
                                        }
				sprintf(strbuf,"%s",buff);
				printf("%s\n",buff);
				strbuf[0]='\0';
                                write(client_sockfd, "MSG Received", 255);
                                printf("전송 완료\n");
                                }
                                if(--fd_num <=0 )
                                        break;
                        }
                }
        }
}
bugiii의 이미지

select 를 해서 넘어온 후 따로 사용하는 fd 들의 상태를 비교하실 필요가 없습니다.

select 후에 fd 의 상태를 따로 알아보는 것이 아니라, 지금 상황같으면 read 비트가 켜져있을 때 read 한번 해보면 read 에서 어떤 값을 돌려주는지를 조사해서 해당 동작을 하시면 됩니다. 만약 접속이 끊겼으면 read 는 0을 돌려줄 것이구요. 다른 에러면 -1을 주겠죠. 정상이라면 읽을 바이트수 나올테구요. 0보다 작거나 같으면 소켓 닫아주면 되고 allfds 에서 제외시켜주시면 됩니다.

아니면 select 에 에러셋을 추가로 설정하시든지요.

select 사용법을 정확하게 다시 알아보시는 것이 좋겠습니다. UNP 에 좋은 설명이 있고, 찾아보시면 select 예제도 꽤 많을 것입니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.