PHP에서 socket_select() 함수에 대한 질문좀..^ ^ ㅋ

naddolki의 이미지

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;
}
?>
==================================================

댓글 달기

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 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.