japanese site
온라인강좌책메일다운로드동아리쇼핑기술지원기업정보갤러리동영상 블로그
『신개념 4단계 리눅스기술지원 시스템 공개』

※ 『무료 리눅스 배포판 배송서비스』 ※

※ 게시판 용도에 맞지 않는 글(광고및 홍보 글 등)은 임의삭제될 수 있습니다.

 
작성일 : 05-05-29 22:19
[꼭!! 좀] socket_select() 함수에 대해 질문합니다.
 글쓴이 : 최경수
조회 : 1,921  

int socket_select(array &read, array &write, array &except, int tv_sec [, int tv_usec])

제가 아는데로라면 ..
socket_select() 는 ..

소켓배열을 인자로 받아, 해당소켓의 입/출력버퍼를 경계하다가 ..
이에 변화가 생기면 변화가생긴 소켓들의 총개수를 반환하는 걸로
알고있습니다.

근데, 사실 이해가 잘 안가는 부분들이 있습니다.
대답좀 부탁드려욧 ㅠㅠ
웹상에서는 찾을 수 없는 답변이더군요.
아마 많은 분들이 궁금해 하시는 부분일 것 같아서 질문을 올립니다.

정말 정성스레 답변 해주시면 ..
지식공유 차 ..
문서로 정리해서 인터넷 여기저기에 올릴려구요 ..

일단 아래의 질문들은 추신부분에 있는 'PHP 소스' 를 보면서 갖게되 었다는 것을
앞서 밝힙니다.

제발 답변 부탁드립니다 ^^


0. 소켓들도 스트림에 대해 입력/출력 버퍼를 이용한다고 하던데 .. 각 소켓마다 할당되는 건가요 ?

1. 전달인자 중 $write는 어떤 의미를 갖는지 구체적인 설명 부탁드려요 ㅠㅠ
(이 배열변수 인자는 어떨때 사용하며, 어떻게 감시되는지 예를 좀 들어주세요.)

2. 전달인자 중 3개의 소켓배열($read, $write, $except)중 하나를 제외한 나머지는
일반적으로 NULL 로 처리해 전달하고, NULL이 아닌 배열만 감시를 하게하는데,
만약 셋다 NULL이 아닌 소켓배열로 전달하면 정상적으로 동작하나요 ?

3. socket_select()에 $read 배열을 구성할 때 ..
$read = array_merge("소켓배열", "소켓배열") 와 같이해서 $read 를 구성하지 않고,
$read = array(소켓1, 소켓2) 와 같이해서 구성했더니 .. "잘못된 인자" 라고 경고가 나오던데 ..
뭐가 잘못된건가요 ..

4. socket_select()에 $read 배열을 넘겼을 때, 이 배열을 구성하는 소켓들을 감시함과 동시에 ..
새로운 "클라이언트의 접속시도" 도 감시한다고 하던데요. 둘 중 어떤 경우에 의해 ..
함수가 종료(블럭킹모드 해제)되었는지 판별할 수 있는 방법이 있나요 ?

5. 만약, $read 배열내의 소켓에 변화가 생긴거라면, 어떤 소켓에 변화가 생긴 것인지 ..
판별하는 방법은 있나요? (어떻게 판별하나요?)

6. $read 배열을 구성하는 소켓들 중 하나에만 변화가 생겨도 함수는 종료(블럭킹모드 해제)되는데,
socket_select()의 리턴값으로 "$read 배열내 변화가 생긴 소켓들의 개수" 가 무슨 의미가 있는지 ..
(리턴값은 항상 1이지 않을까요? - timeout 과 오류가 없는한..)

7. $read 배열구성시에, 일반적으로 $read = array_merge("서버소켓배열", "클라이언트소켓배열")과
같이 해주던데.. $read 를 처음구성할 때, 연결되어 있는 클라이언트소켓이 없기 때문에,..
비어있는 클라이언트소켓을 사용하는데 ..
서버소켓과 비어있는 클라이언트 소켓으로 구성해서 socket_select()에 전달하는 이유가 무엇인가요?
(어차피, 새로운 "클라이언트의 접속시도"에 대한 소켓 디스크립터는 .. 이 접속에 의해 socket_select()
가 종료된 후 socket_accept()로 클라이언트 소켓을 받아들일때 할당하면 되는거잖아요. 근데, 굳이 빈
클라이언트 소켓을 $read 배열의 원소로 끼워넣는 이유가 무엇일까요?)


P.S. socket_select()를 사용한 소켓프로그래밍 소스.
==================================================
#!/home/dimeclub/www/bin/php/php -q
<?php

//
// 클라이언트로부터 quit 문자열을 받았을 때, 종료되는 서버스크립트입니다.
//

set_time_limit(0);

define("_IP",    "111.222.333.12");
define("_PORT",  "65000");
define("_TIMEOUT", 10);

// cSock -> Client Socket
// cInfo -> Client Information from Client Socket
// sSock -> Server Socket

$cSock = array();
$cInfo = array();
$sSock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

socket_bind($sSock, _IP, _PORT);
socket_listen($sSock);

while(1)
{
    $sockArr = array_merge(array($sSock), $cSock);
    if(socket_select($sockArr, $tWrite = NULL, $tExcept = NULL, _TIMEOUT) > 0)
    {
        foreach($sockArr as $sock)
        {
            // Listen 하고 있는 서버 소켓일 경우
            // 새로운 클라이언트의 접속을 의미
            if($sock == $sSock)
            {
                $tSock = socket_accept($sSock);

                socket_getpeername($tSock, $sockIp, $sockPort);

                $cSock[$tSock] = $tSock;
                $cInfo[$tSock] = array('ip'=>$sockIp, 'port'=>$sockPort);

                msg("client connect : ".$sockIp.":".$sockPort."\n");
            }
            // 클라이언트 접속해 있는 소켓중 하나일경우
            // 해당 클라이언트에서 이벤트가 발생함을 의미
            else
            {
                $buf = socket_read($sock, 4096);

                // 접속 종료
                if(!$buf)
                {
                    exceptSocket(&$cSock, &$cInfo, $sock);
                    msg("client connection broken : ".$sockIp.":".$sockPort."\n");
                }
                // 메시지 수신 이벤트
                else
                {
                    msg("recive data : ".$buf."\n");
                    $thisSockInfo = $cInfo[$sock];
                    $cmd = substr($buf, 0, 4);
                    switch($cmd)
                    {
                        // 시간전송
                        case "time":
                            msg("client(".$thisSockInfo['port'].") time data request\n");
                            socket_write($sock, date("Y/m/d H:i:s"));
                            break;

                        // 종료
                        case "quit":
                            msg("client(".$thisSockInfo['port'].") quit request\n");
                            socket_write($sock, "quit");
                            socket_close($sock);
                            exceptSocket(&$cSock, &$cInfo, $sock);
                            break;
                        default:
                            msg("client(".$thisSockInfo['port'].") invalid command $cmd\n");
                            break;
                    }
                }
            }
        }
    }
}

function exceptSocket(&$sockSet, &$infoSet, $sock)
{
    unset($sockSet[$sock]);
    unset($infoSet[$sock]);
    // array_merge 함수에서 error 발생을 막기위한 처리
    if(count($sockSet)==0)
    {
        $sockSet = array();
        $infoSet = array();
    }
}

function msg($msg)
{
    echo "SERVER >> ".$msg;
}
?>
==================================================


이 글을 트위터로 보내기 이 글을 페이스북으로 보내기

 
   
 


『신개념 4단계 리눅스기술지원 시스템 공개』

CentOS 리눅스 전문서적 국내최초출시

 
회사소개 | 보도기사 | 채용안내 | 광고안내 | 이용약관 | 개인정보취급방침 | 책임한계와 법적고지 | 불편사항 신고하기 | 사이트맵
ㅇ 서울 : 서울특별시 강남구 노현로79길 66, 402호(역삼동,청송빌딩)  ㅇ 부산 : 부산광역시 해운대구 우동 1470 에이스하이테크21 914호
ㅇ 대표 : 1544-8128 ㅇ부산직통 : 051-744-0077 ㅇ서울직통 : 02-856-0055 ㅇ FAX : 02-6280-2663
ㅇ 사업자번호 : 128-86-68239 ㅇ 통신판매업 신고번호 : 2013-부산금정-0035호 ㅇ 개인정보책임자 : 이재석
ㅇ 상호명 : (주) 수퍼유저 ㅇ 대표자 : 박성수
Copyright ⓒ (주)수퍼유저. All rights reserved.

 아 이 디
 비밀번호
회원 가입 | 비밀번호 찾기

블로그~
 
▷ 질문과 답변
리눅스
서버해킹/보안
네트워크
아파치
메일서버
DNS
PHP
JSP
MySQL
큐브리드
Oracle
MRTG
SMS
Weblog
Domain
S/W
하드웨어
책제목
리눅스서버관리실무바이블v3.0


저자 박성수
페이지수 2,032 pages
펴낸곳(주)수퍼유저

리눅스 서버 구축 및 관리에 필요한 거의 모든 부분과 전반적인 실무 기법들을 다루고 있음
책제목
리눅스보안관리실무(2/E)


저자홍석범
페이지수 820 pages
펴낸곳(주)수퍼유저

리눅스 보안에 관련된 내용을 종합적으로 쓴 책. 저자의 명성 그대로 보안관련의 모든 내용이 그대로 담겨져 있다.