[김성민]님이 남기신 글:
>
>php 로 소켓서버 하는 소스인데요.. --> server.php
>
>#!/usr/local/bin/php -q
><?
>set_time_limit(0);
>
>define("_IP", "111.222.333.12");
>define("_PORT", "8888");
>
>$sSock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
>
>socket_bind($sSock, _IP, _PORT);
>socket_listen($sSock);
>
>pcntl_signal(SIGCHLD, SIG_IGN);
>
>while($sock = socket_accept($sSock))
>{
> socket_getpeername($sock, $sockIp, $sockPort);
> msg("client connect :
".$sockIp.":".$sockPort."\n");
>
> $pid = pcntl_fork();
> msg("fork\n");
> if($pid == -1)
> {
> msg("fork failed\n");
> exit;
> // 자식 프로세스 일때
> }if($pid == 0)
> {
> while(1)
> {
> $buf = socket_read($sock, 4096);
>
> // 접속 종료
> if(!$buf)
> {
> msg("client connection broken :
".$sockIp.":".$sockPort."\n");
> exit;
> }
> // 메시지 수신 이벤트
> else
> {
> msg("recive data : ".$buf."\n");
> $cmd = substr($buf, 0, 4);
> switch($cmd)
> {
> // 시간전송
> case "time":
> msg("client(".$sockPort.") time data
request\n");
> socket_write($sock, date("Y/m/d
H:i:s"));
> break;
>
> // 종료
> case "quit":
> msg("client(".$sockPort.") quit
request\n");
> socket_write($sock, "quit");
> socket_close($sock);
> exit;
> break;
> default:
> msg("client(".$sockPort.") invalid command
$cmd\n");
> break;
> }
> }
> }
> }
>}
>
>function msg($msg)
>{
> echo "SERVER >> ".$msg;
>}
>?>
>
>
>이게 해보니 되기는 하는데, 클라이언트가 server.php 실행되고
있는 서버에 8888 포트로 최초 접속하고 아무입력 없이 가만히
있으면 server.php 에서도 자식프로세스가
무한정 살아있는 상태라는것과, $cmd 에 해당하는 클라이언트->
서버. 로 어떠한 메시지를 던지고 나서 아무것도 안하고 있으면
마찬가지로 무한정 대기 상태라는 문제가 있는데요..
>
>처음접속시나 접속후, 어떠한 메시지를 던지로 나서 아무것도
안하고 00초 있으면 클라이언트 연결이 자동으로 끊어지도록
하는걸 해보려고 하는데 도무지 안되서요..
>
>혹. 이 부분에 대해 처리방법을 아시는지 해서 문의드립니다..
========================================
저 같은 경우는 sokect_select 기반으로 작년초에 ICAP 서버를
만들어서 서비스에 사용중이랍니다(회사에서
사용중이라서 소스 공개는 힘들것 같습니다).
- 시그널 처리
- 소켓 옵션 설정
- timeout 설정
- socket_read/write 튜닝
- 부하/메모리 사용량 등등
이렇게 더 보안해야 할 부분이 꽤 많습니다(아주 단순하게 짜도
1000줄이 넘습니다).
우선 client 수가 꽤 많고 Server 측에서 socket 를 강제로 먼저 close
하면 나중에 TIME_WAIT 상태가 꽤 많아지는 문제가 생깁니다.
때문에 가능한 Server 측에서 강제로 종료하는 것은 바람직하지
못합니다. 어쩔 수 없는 경우는 제외하고요.
따라서 client 에서 close 하는 방법을 택하십시오.
그외 Server 에서 close 하려면,
while(1)
{
// A. 이부분에 timeout 체크하여 close 함
...
$buf = socket_read($sock, 4096);
...
}
timeout 에 대한 start 는
1. 제일 처음 접속시
2. 해당 client socket 에 socket_write() 할 때(1 에 대해서 override)
즉 위의 A 부분에서 얼마나 시간이 흘렀는지 체크해서 너무
길게 종료안되어 있으면 강제종료하는 식으로 프로그래밍
하시면 됩니다.
키포인트는 while() 문 안이나 socket_select() 방식일 경우는 문
안입니다.
|