필요에 의해 html -> php -> java api로 파일을 전송해야 할 일이 생겼다.

Java Api는 UI에서 바로 사용하면 안되는 상태라서 php를 거쳐 가야 하는데 html에서 올린 파일을 Java API로 전달 하는 과정이 생각보다 쉽지 않아 정리 차원에서 글을 남긴다.


Html에서 php로 파일을 올리게 되면 $_FILES 라는 전역변수 안에 정보가 담기고, 실제 파일은 php.ini에서 지정한 임시 디렉토리에 저장된다.

해당 경로는 $_FILES['업로드한 html form name']['tmp_name'] 에 저장되어 있으며, 해당 파일을 다시 Java API 쪽으로 넘겨 주면 된다.


넘겨주는 방법은 curl을 사용하면 된다.

다음과 같은 방법으로 하면 된다.






Content-Type을 multipart/form-data로 셋팅하는 부분은 많지만, 많이 찾기 힘들었던 부분은 ".';filename='.$file['name'].';type='.$file['type']" 이다.

html에서 php로 업로드 한 파일은 image/png 인데 php에서 Java로 curl을 통해 업로드 하게 되면, 기본적으로 application/octet-stream 타입으로 업로드 되기 때문이다.

이 부분을 html에서 업로드 한 그대로 by pass 하기 위해서는 위 소스와 같이 값을 지정해 주면 된다.


그 후 $response에서 받은 Json 값을 파싱하면 되는데

$response에는 header 정보도 같이 들어오게 되므로 body만 별도로 분리해야 한다.



이렇게 하게 되면 header를 제외한 순서 Json body 부분만 받을 수 있게 된다.

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret

오랜만에 php 코드를 들여다 볼 일이 생겼는데, 알지 못할만한 소스코드들이 있어 헤메다가 정리 차원에서 적어둔다.


1. php의 람다식.


http://php.net/manual/kr/function.array-walk.php

array_walk($data, function(&$value, $key, $joinUsing) { 

$value = $key . $joinUsing . $value; 

}, $glue);


array_walk의 2번째 인자값을 function 변수로 넘길 수도 있지만 위에처럼 람다식으로 그냥 적어버릴 수 있다.

안드로이드에서 Callback 함수로 람다식으로 적는 경우가 많은데, 그런식으로 작성하나 보다. 오랜만에 php 하니 새롭다 ^^;;


2. 가변함수


이런말 첨 들어보는데, 위의 array_walk가 만일 유저 정의 함수라면 함수 내에서 두번째 인자값을 받아다가 사용할 수 있다.

두번째 인자를 $func 이란 변수로 받는다면 함수 자체는 $func() 과 같이 사용할 수 있다.

이와 관련한 것도 php.net에서 간단한 예제를 볼 수 있다.


http://php.net/manual/kr/functions.variable-functions.php

function foo() {

    echo "foo() 안입니다.<br />\n";

}


$func = 'foo';

$func();        // foo()를 호출합니다.


저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
XE의 mysqli 환경 가운데서 발생하는 오류를 잡기 위해 테스트 하다가 설치 후 초기 화면 조차 보이지 않는 문제를 당면하게 되었다.

맞닥뜨리게 된 에러는 다음과 같다.


Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 4294967296 bytes) in .../classes/db/DBMysqli.class.php on line 234


4G 메모리 할당을 하다가 오류가 발생했다는 오류였다.

대부분 memeory 할당 오류는 php.ini 또는 ini_set을 통해 해결할 수 있다는 답변 뿐이였다.

예를 들어 http://www.xpressengine.com/qna/20836943 이런 식 ^^;;


그런데 php.ini에서 메모리를 4G 이상 5G를 줘도 문제가 발생했고

메모리의 제한이 없도록 -1을 준 경우에는 서버의 메모리를 다 쓰게 되어서 서버가 멈추는 현상까지 벌어지게 되었다.


따라서 처음에는 XE의 문제인줄 알고 Source code를 수정하고자 Debuging을 열심히 하였지만 도저히 방법이 보이지 않았다.


그러다가 4G라는 크기에 눈이 가게 되었고, 4G는 MySQL의 longtext type의 크기라는 것에 시선이 고정되게 되었다.

이를 기초로 구글링을 해보니 어떤 검색 결과에서는


CAST(`modules`.`content` AS char(20000))


와 같이 longtext type의 column의 type cast를 하라는 말이 나와 있었다.

물론 위와 같이 하니까 문제 없이 해결은 되었지만...

길이가 다르니 내용까지 짤려서 보일 듯 싶어서 왠지 깨름직 했다.


왠지 해결책은 매뉴얼에 있을 듯 싶어 php 매뉴얼을 뒤졌더니


http://kr2.php.net/manual/en/mysqli-stmt.bind-result.php#101543


위와 같이 똑같은 증상을 호소하는 사람이 있었다.

해당 내용에 연결된 버그리포트에는 해당 내용이 버그가 아니며 mysql 버그로 보인다라는 말이 있었다.

따라서 php 재설치 시 다음과 같은 옵션으로 설치해 보면 된다고 했다.


--with-mysql=mysqlnd
--with-mysqli=mysqlnd
--with-pdo-mysql=mysqlnd
--enable-mysqlnd


mysqlnd로 구글링 해 보니 또한 다음과 같은 문서도 나오더라.


http://www.lovelgw.com/Blog/316


애초에 설치 시에는 옵션을


--with-mysql=/usr/local/mysql \
--with-mysqli=/usr/bin/mysql_config \


와 같이 줬는데 mysqlnd로 옵션을 바꿔 설치하니 이상없이 동작을 하게 되었다.


하루종일 이 문제로 구글링 하고 디버깅 했는데 결국 해결을 하게 되어 한시름 놓을 수 있게 되었다.


신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret

이진우

프리랜서
프로그래머

            
          


이문서의 배포는 자유로우나 최소한 제작자의 정보는 제외하지 않고 배포해 주세요.

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(http://www.jinoos.com)에서만 받습니다.


1. 소개

이번강좌에는 fork를 이용해서 새로운 프로세스를 생성하여 생성된 자식 서버프로세스가 클라이언트를 담당하는 형태를 구연해 보겠습니다.

PHP에서 fork함수로는 Process Control 함수의 pcntl_fork() 함수가 있습니다. Process Control 함수는 기본함수가 아니기 때문에 컴파일시 옵셥으로 추가시켜야 합니다.


2. pcntl_fork() 함수

int pcntl_fork ( )

함수 호출후 리턴값에 0이면 자식 프로세스이며 >0 이면 부모 프로세스로 자식 프로세스의 PID번호를 리턴 받습니다. error발생시에는 -1 값을 가집니다.

포크 함수는 포크 함수를 실행한 프로세스와 동일한 자식 프로세스를 생성합니다. 동일한 자식 프로세스라는 의미는 프로세스 계보상의 깊이만 다를뿐 동작은 똑같은 쌍둥이를 만드는 것 입니다.

자식 프로세스는 부모 프로세스의 메모리를 복사해서 클론을 만들고 리소스(파일 지시자, DB 커넥션, 소켓 커넥션 등)은 공유합니다.

간단하게 pcntl_fork() 코드를 살펴 보겠습니다.

<?php
$i = 0;
$pid = pcntl_fork();

// error
if($pid == -1)
{
    echo "fork error";

// 부모 프로세스
}elseif($pid > 0)
{
    for(;$i<10;$i++)
    {
        echo "Parent Process \$i : $i\n";
    }

// 자식 프로세스
}elseif($pid == 0)
{
    for(;$i<10;$i+=2)
    {
        echo "Child Process \$i : $i\n";
    }
}
?>
                    
부모 프로세스는 $i 값이 1씩, 자식 프로세스는 $i 값이 2씩 증가하는 프로그램 입니다. 결과는 각자 해보시기 바랍니다.


3. PHP 컴파일 하기

첫번째 강좌(PHP를 이용한 다중 연결 소켓 통신 (1)) 에서 소켓 함수를 사용하기 위해 --with-sockets 옵션을 주어 컴파일 하였습니다.

오늘은 소켓 함수와 Process Control 함수를 추가시켜 컴파일 해보겠습니다.

#] tar -zxvf php-4.3.1.tar.gz
#] cd php-4.3.1
#] ./configure --with-sockets --enable-pcntl
#] make

역시 php 실행파일이 생성됩니다.


4. 프로그램 작성

오늘 작성할 서버와 클라이언트의 구조는 아래와 같습니다.

                                ┌───────┐            ┌───┐
                    ┌─(Fork)─┤Child Process ├─(socket)─┤Client│
                    │          └───────┘            └───┘
┌───────┐  │          ┌───────┐            ┌───┐
│Master Process├─┼─(Fork)─┤Child Process ├─(socket)─┤Client│
└───────┘  │          └───────┘            └───┘
                    │          ┌───────┐            ┌───┐
                    └─(Fork)─┤Child Process ├─(socket)─┤Client│
                                └───────┘            └───┘
좀더 단순화 되고 직관적으로 표현되었군요.

Child Process 한나가 Client 하나를 독립적으로 마크하는 구조입니다.

연결이 끊어진 Child Process는 바로 소멸됩니다. 새로운 클라이언트가 참여하면 바로 Master Process는 pcntl_fork함수를 이용해서 Child Process를 생성하죠.


4.1. 서버 만들기

서버의 구조를 간단히 살펴보면

소켓생성
소켓바인트및 리슨
while(새로운연결수락)
{
    포크
    if(자식프로세스)
    {
        while(메시지수신)
        {
            메시지 처리
            if(quit메시지)
            {
                소켓닫기
                종료
            }
        }
    }
}
            
구조 입니다. 메시지 처리 부분은 지난 강좌(PHP를 이용한 다중 연결 소켓 통신 (2))의 메시지 처리 부분과 동일하며 select처리 대신 fork를 이용한 처리 입니다.

#!/usr/local/bin/php -q
<?php
set_time_limit(0);

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

$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로 저장하고 실행권한을 줍니다.


4.2. 클라이언트 만들기

클라이언트는 지난 강좌지난 강좌(PHP를 이용한 다중 연결 소켓 통신 (2))에서 사용한 클라이언트 프로그램을 수정없이 그대로 사용합니다.


4.3. 실행하기

server.php를 실행후 client.php를 3번 실행하고 프로세스와 프로세스 트리를 확인해보겠습니다.

server.php 실행 화면

#] ./server.php 
SERVER >> client connect : 111.222.333.12:38276         -- (1)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38276) time data request
SERVER >> client connect : 111.222.333.12:38396         -- (2)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38396) time data request
SERVER >> client connect : 111.222.333.12:38559         -- (3)
SERVER >> fork
SERVER >> fork
SERVER >> recive data : time
SERVER >> client(38559) time data request              -- (4)
SERVER >> recive data : quit
SERVER >> client(38276) quit request                   -- (5)
SERVER >> recive data : quit
SERVER >> client(38396) quit request                   -- (6)
SERVER >> recive data : quit
SERVER >> client(38559) quit request                   -- (7)

client는 (1), (2), (3)에서 3번 실행하여 동일하게 time 메시지를 송신 및 데이타를 수신하고 하고 quit 했습니다.

#] ./client.php 
CLIENT >> socket connect to 111.222.333.12:65000
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/21 16:18:34
CLIENT >> Enter command time or quit : quit
CLIENT >> Input command : quit
#] 

아래는 (3),(7)시점에서 두번 프로세스 현황을 확인(ps, pstree)한 결과 입니다.

#] ps -xa | grep server.php
30947 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31203 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31287 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31372 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31467 pts/7    S      0:00 grep server.php
#] pstree
init-+-crond
    ...
    ...
     |-sshd-+-sshd---bash---server.php---3*[server.php]
     |      |-3*[sshd---bash---client.php]
     |      `-sshd---bash---pstree
    ...
    ...
     `-xinetd
#]
#] ps -xa | grep server.php
30947 pts/3    S      0:00 /usr/local/bin/php -q ./server.php
31521 pts/7    S      0:00 grep server.php
#] pstree           
init-+-crond
    ...
    ...
     |-sshd-+-sshd---bash---su---bash---server.php
     |      |-3*[sshd---bash]
     |      `-sshd---bash---pstree
    ...
    ...
     `-xinetd
#]          
(3) 시점에는 fork 3번 실행한 순간이므로 부모 프로세스와 자식 프로세스 3개, 총 4개의 프로세스가 실행되고 있는것을 확인할수 있습니다.

pstree의 경우는 server.php---3*[server.php]처럼 Master Process 한개 Child Process 3개로 표현되어 있습니다. 문론 메시지도 잘 전송 되었구요.. ^^


5. 결론

오늘은 PHP의 Process Control Function을 이용하여 다수의 클라이언트 요청처리를 해보았습니다.

fork방식은 select방식보다 간단한 구조로 구현하기 간편하다는 장점도 있지만, 다중 프로세스 구조라 프로세스간 통신을 위해서 부차적인 IPC를 구현해야 할 상황이 생길수도 있다는 점이 단점이라 할수 있습니다.

다음 강좌에는 mysql과 지금까지 배운 소켓 통신을 가지고 간단한 채팅 클라이언트/서버를 만들어 보겠습니다.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret

이진우

프리랜서
프로그래머

            
          


이문서의 배포는 자유로우나 최소한 제작자의 정보는 제외하지 않고 배포해 주세요.

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(http://www.jinoos.com)에서만 받습니다.


1. 소개

저번강좌(PHP를 이용한 다중 연결 소켓 통신 (1))에 간단한 서버/클라이언트 프로그램을 만들어 보았습니다. 하지만 이것은 많은 부분이 부족하다는 생각들을 하셨을껍니다.

오늘 시간에는 socket_select() 함수를 통해서 다중의 클라이언트 요청을 처리하는 프로그램을 짜 보겠습니다.


2. SELECT

저번강좌(PHP를 이용한 다중 연결 소켓 통신 (1))의 server.php 에서

while($cSock = socket_accept($sSock))
{
    $date = date("Y/m/d H:i:s");
    socket_write($cSock, $date);
    socket_close($cSock);
}

위코드는 클라이언트 소켓이 접속하기를 대기하는 동작입니다. 하지만 socket_accept()함수는 호출된뒤에 소켓연결 요청이 들어오면 요청 처리를 하게 됩니다. 프로그램 상에선 메시지를 전송하고 곧바로 클라이언트와 소켓을 종료하고 다시 accept 상태(blocking모드)로 전환되는 형태입니다.

이와같은 경우는 접속된 클라이언트와 소켓 접속이 반드시 끊어져야(아니면 당연히 끊어야 한다던지) 다른 클라이언트의 접속을 처리 할수 있습니다. 하지만 불규칙 적으로 클라이언트가 서버에 요청(소켓접속이 아님)을 하는 상황이라면 문제가 될것이 자명 합니다.

이와 같은 상황을 처리 하기 위해서 다량의 socket묶음을 동시에 감시하는 SELECT가 있습니다. PHP에서는 socket_select() 함수가 바로 그것입니다.


2.1. socket_select() 함수

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

read 인자에는 읽기 이벤트를 감시할 Socket Array가 참조됩니다. socket_select() 함수는 Array 묶음으로 들어오는 소켓들을 감시하다가 이벤트가 발생하면 해당인자를 읽기 이벤트가 발생한 Socket Array로 변환하고 Blocking 상태가 해제 됩니다.

write 인자역시 read 인자와 같은 역할로 쓰기 이벤트가 발생할시에 사용된다.(하지만. -_- 어디에 필요하단 말인가. 본인은 이부분이 이해가 잘 안간다. 혹시 알고있다면 알려주기 바란다. except 역시 본인이 사용법을 알아내지 못했다.)

중요한 인자인 tv_sec는 select가 block 모드로 대기하고 있는 timeout을 설정합니다. 이것을 유용하게 이용하면 일정간격으로 어떠한 작업을 수행하는것도 가능합니다. NULL로 설정하면 timeout없이 대기 합니다.


3. 프로그램 작성

전장에서 select 함수에 대해 몇가지를 알아 보았습니다. 부족하지만 사용하기엔 크게 문제가 없을 것입니다.

오늘 작성한 프로그램은 저번강좌(PHP를 이용한 다중 연결 소켓 통신 (1)) 에서 작성한 프로그램과 기능은 같지만 약간 복잡한 형태입니다.

서버소켓을 생성한뒤에 클라이언트를 대기하고, 클라이언트가 접속하면 클라이언트 소켓을 클라이언트 소켓 묶음으로 저장한뒤에 감시합니다. 새로운 클라이언트가 접속하면 다시 클라이언트 묶음에 저장하고 감시를 반복하며, 클라이언트에서 time라는 메시지를 수신하면 현재 시간을 바로 송신하고, quit라는 메시지를 수신하면 클라이언트와 접속을 끊습니다.


3.1. 서버 만들기

시작코드는 저번 강좌와 많이 비슷합니다. 다만 무한 루프를 돌면서 서버 소켓과 클라이언트 소켓 묶음을 Array로 생성하여 select의 Read 이벤트를 감시합니다.

...
while(1)
{
    $sockArr = array_merge(array($sSock), $cSock);
    if(socket_select($sockArr, $tWrite = NULL, $tExcept = NULL, _TIMEOUT) > 0)
    {
        ... (1)
    }
}
...
Write 이벤트와 Except 이벤트는 무시하기 위해서 NULL 처리 되었습니다. timeout은 주어졌지만 본 프로그램에선 크게 의미 없는 상황입니다.

위 코드중 socket_select()에서 이벤트가 발생되면 $sockArr 변수에 리턴된 Array를 (1)에서 분석합니다.

        ...
        foreach($sockArr as $sock)
        {
            if($sock == $sSock)
            {
                ... // (2)
            }else
            {
                ... // (3)
            }
        }
        ...
서버 소켓에 클라이언트가 접속을 요청했을때 $sockArr에 서버 소켓이 리턴됩니다. 그리하여 (2)에서 클라이언트 소켓을 socket_accept()함수로 접속을 허용합니다.

만약 리턴된 소켓이 서버 소켓이 아니라면 클라이언트와 통신중인 소켓입니다. 당연하겠죠. array_merge(array($sSock), $cSock) 로 서버 소켓과 클라이언트 소멧만을 merge했으니까요.

(3)에서는 클라이언트에서 보내는 정보를 읽어들이고 이를 분석해서 처리 하는 부분이 들어 갑니다. 유의해서 봐야 할 부분은

                $buf = socket_read($sock, 4096);

                // 접속 종료
                if(!$buf)
                {
                }
                // 메시지 수신 이벤트
                else
                {
                }
$buf 의 내용이 없을때 클라이언트가 접속을 종료함을 의미 한다는 것입니다.

자 그럼 이제 실제 코드를 보겠습니다.

#!/home/dimeclub/www/bin/php/php -q
<?php
set_time_limit(0);

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


$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;
}
?>
server.php로 저장합니다. 역시 실행권한은 있어야 겠지요.


3.2. 클라이언트 만들기

클라이언트 역시 몇가지를 수정하여 쉘에서 사용자의 입력을 받아 들이도록 처리하였습니다.

클라이언트는 서버와 소켓을 연결한뒤 사용자의 키입력을 기다렸다 time을 입력시 서버에 time메시지를 전송하고 quit입력시 프로그램을 종료 합니다. PHP CGI를 이용해서 사용자 키입력을 받아들이는 역할은 아래 함수처럼 구현되었습니다.

function read_data()
{
    $in = fopen("php://stdin", "r");
    $in_string = fgets($in, 255);
    fclose($in);
    return $in_string;
}
fopen("php://stdin", "r") 로 원래 의미는 리눅스 시스템에서 fopen("/dev/stdin", "r"), fopen("/proc/self/fd/0", "r"), fopen("dev/fd/0", "r") 입니다. 표준입력을 받아들이는 역할로 사용자 키입력을 받아들이죠.

만약 표준출력 또는 표출에러 출력을 받아들이려면 fopen("php://stdout","r"), fopen("php://stderr", "r") 로 구현할수 있습니다.

클라이언트는 time 라는 서버에 시간 데이터를 요청하는 메시지와 quit 라는 종료 두 메시지를 제외하고는 나머지는 무시합니다. 코드상에는 invalid command (not send) 라고 출력하지만 그이상의 어떠한 행동도 하지 않고 무시해 버립니다.

#!/home/dimeclub/www/bin/php/php -q
<?php
define("_IP",    "111.222.333.12");
define("_PORT",  "65000");

$sock      = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($sock, _IP, _PORT);
msg("socket connect to "._IP.":"._PORT."\n");

while(1)
{
    msg("Enter command time or quit : ");

    // 사용자의 명령어를 입력받습니다.
    $stdin = ereg_replace("\n|\r", "", read_data());
    $stdin = substr($stdin, 0, 4);
    
    // time 또는 quit 메시지 말고는 무시 합니다.
    if($stdin == "time" || $stdin == "quit")
    {
        msg("Input command : ".$stdin."\n");
    }else
    {
        msg("invalid command (not send) : ".$stdin."\n");
        continue;
    }

    socket_write($sock, $stdin);
    $sMsg  = socket_read($sock, 4096);
    if(substr($sMsg, 0, 4) == 'quit')
    {
        socket_close($sock);
        exit;
    }else
    {
        msg("recived data : ".$sMsg."\n");
    }
}

// 표준입력을 받아 값을 리턴하는 함수
function read_data()
{
    $in = fopen("php://stdin", "r");
    $in_string = fgets($in, 255);
    fclose($in);
    return $in_string;
}

// 로그를 출력합니다. 디버그용
function msg($msg)
{
    echo "CLIENT >> ".$msg;
}
?>

특별히 난해한 부분은 없을꺼라 생각합니다. 역시 위 소스를 client.php로 저장하고 실행권한을 줍니다.


3.3. 실행하기

서버를 실행하고 클라이언트를 실행합니다. 클라이언트#1을 실행후 time 메시지를 날리면서 클라이언트#2 실행후 종료, 클라이언트#3 실행후 종료, 그리고 다시 클라이언트#1을 종료 하였습니다.

클라이언트#1

#] ./client.php 
CLIENT >> socket connect to 111.222.333.12:65000
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:29
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:34
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:41
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:50
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:57
CLIENT >> Enter command time or quit : quit
CLIENT >> Input command : quit
#]

클라이언트#2,#3

#] ./client.php 
CLIENT >> socket connect to 111.222.333.12:65000
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:31
CLIENT >> Enter command time or quit : quit
CLIENT >> Input command : quit
#] ./client.php 
CLIENT >> socket connect to 111.222.333.12:65000
CLIENT >> Enter command time or quit : time
CLIENT >> Input command : time
CLIENT >> recived data : 2003/05/09 22:32:47
CLIENT >> Enter command time or quit : quit
CLIENT >> Input command : quit
#] 

같은 상황의 서버쪽 실행화면입니다.

#] ./server.php 
SERVER >> client connect : 111.222.333.12:32850        -- (4)
SERVER >> client connect : 111.222.333.12:32868        -- (5)
SERVER >> recive data : time
SERVER >> client(32850) time data request
SERVER >> recive data : time
SERVER >> client(32868) time data request
SERVER >> recive data : time
SERVER >> client(32850) time data request
SERVER >> recive data : quit                          
SERVER >> client(32868) quit request                  -- (6)
SERVER >> recive data : time
SERVER >> client(32850) time data request
SERVER >> client connect : 111.222.333.12:32938        -- (7)
SERVER >> recive data : time
SERVER >> client(32938) time data request
SERVER >> recive data : time
SERVER >> client(32850) time data request
SERVER >> recive data : quit             
SERVER >> client(32938) quit request                  -- (8)
SERVER >> recive data : time
SERVER >> client(32850) time data request
SERVER >> recive data : quit
SERVER >> client(32850) quit request                  -- (9)

(4)에서 클라이언트포트 32850, (5)에서 32868 이렇게 두개의 클라이언트가 접속했습니다. 서버는 두개의 클라이언트에서 time 메시지를 수신하면서 동작하다 (6)에서 하나의 클라이언트가 접속을 종료하고 (7)에서 다시 하나의 클라이언트가 32938 클라이언트 포트로 다시 접속했습니다. 그리고 다시 time 메시지를 주고 받다 (8)에서 하나의 클라이언트가 퇴장하고 그리고 (9)에서 마지막 클라이언트 까지 종료 되었습니다.

32850, 32868 그리고 32938이 각각 클라이언트 #1, #2, #3 입니다.


4. 결론

오늘은 SELECT라는 함수를 이용한 다중 소켓 연결 서버를 만들어 보았습니다. SELECT는 간단한 구조에서 다중의 클라이언트를 받아들일수 있는 방법으로 이용됩니다. 또한 SELECT 기능은 단일소켓연결의 timeout 구현에도 사용할수 있는데 이것은 여러분들이 해보시기 바랍니다.

다음 강좌에서는 PHP의 Process Control Functions을 이용해서 Fork를 이용한 다중 연결 소켓 통신을 해보겠습니다.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret

from phpschool

이진우

프리랜서
프로그래머

            
          


이문서의 배포는 자유로우나 최소한 제작자의 정보는 제외하지 않고 배포해 주세요.

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(http://www.jinoos.com)에서만 받습니다.


1. 소개

앞으로 몇번에 걸처서 PHP를 이용한 다중 연결 소켓 통신에 대해서 알아보겠습니다. PHP는 확장 함수로 socket 계열 함수를 지원합니다. 하지만 이것은 컴파일시 --with-socket 옵션을 주어 컴파일 해야 합니다. 클라이언트 소켓에 관한 함수 fsockopen()는 이곳에서 사용하지 않습니다.


1.1. PHP 컴파일 하기

앞으로 설명할 내용들은 일반적인 아파치 모듈로서의 PHP가 아닌 독립적으로 실행 가능한 PHP CGI형태입니다. 이를 위해서 재 컴파일이 필요하며 이때 소켓에 관한 옵션을 추가하게 됩니다.

PHP 4.3.1 버전을 이용했습니다.

#] tar -zxvf php-4.3.1.tar.gz
#] cd php-4.3.1
#] ./configure --with-socket
#] make

make 를 한후 make install 을 하지말고 php-4.3.1 디렉터리를 보면 php 라는 실행파일이 생성된것을 알수 있다. 그럼 이제 프로그램 짤 준비는 다�다. 간단한가? 간단하다. -_-a


1.2. PHP의 소켓 함수

PHP의 소켓 함수 몇가지를 알아보고 넘어 가도록 하자. PHP의 소켓 함수는 C sys/socket.h 에 정의 되어있는 함수들과 매우 유사하다. 참고 하도록 하자.

socket_create ( int domain, int type, int protocol )

소켓의 연결 자원을 생성 합니다. 소켓 함수를 사용할때 기본으로 쓰입니다.

domain 파라메터에는 AF_UNIX 또는 AF_INET 으로 유닉스 도메인 소켓 또는 인터넷 소켓으로 지정합니다.

type 파라메터에는 STREAM, SOCK_DGRAM, SOCK_SEQPACKET, SOCK_RAW, SOCK_RDM, or SOCK_PACKET 등의 소켓의 종류가 설정 됩니다.

protocol 파라메터에는 TCP또는 UDP 설정(SOL_UDP or SOL_TCP)을 합니다.

socket_connect ( resource socket, string address [, int port] )

서버소켓으로 접속할때 사용하는 함수. 소켓 클라이언트에서 사용하는 함수 입니다.

socket_setopt ( resource socket, int level, int optname, int )

소켓에 옵션을 지정합니다. 크게 중요하지 않은 함수 입니다.-_-

socket_bind ( resource socket, string address [, int port] )

서버 소켓에 주소와 포트번호를 부여 합니다. 서버 소켓에서 필수적인 작업입니다.

만약 AF_UNIX로 지정했다면 port 파라메터는 생략이 가능합니다.

socket_listen ( resource socket [, int backlog] )

서버 소켓을 클라이언트 대기 상태로 만듭니다.

socket_listen() 함수를 호출한 이후부터 서버 소켓은 클라이언트가 접속하는지 아닌지 귀를 기울이는 일을 하게 되는겁니다. 서버 소켓 사용에서 필수 적입니다.

backlog 파라메터는 받아들일 클라이언트의 최대 수를 지정합니다. 생략하면 최대 갯수로 설정됩니다.

리눅스에서 소켓의 최대 갯수는 ulimit -a 를 해보시면 open files 항목이 소켓 최대 갯수와 상응합니다.

socket_accept ( resource socket )

클라이언트 접속을 허가 할때 사용하는 함수 입니다.

함수 호출후 새로운 소켓 리소스가 리턴되는데 이것은 기존에 서버 소켓 리소스에서 생성된 클라이 언트와 통신하는 새로운 소켓 리소스 입니다.

socket_getpeername ( resource socket, string &addr [, int &port] )

클라이언트의 접속 정보를 가져 옵니다.

socket_read ( resource socket, int length [, int type] )

소켓에서 length만큼의 정보를 읽어 들입니다.

type 읽어들일 타입을 결정 합니다.

  • PHP_BINARY_READ : 바이너리 타입으로 읽어 들입니다. 4.1.0 포함 버전 이후부터 기본값으로 설정되었습니다.

  • PHP_NORMAL_READ : \r또는 \n이 입력될때 끊어서 읽습니다. 한마디로 라인 단위로 읽는 다는 말이죠. 4.1.0이전 버전에선 기본값.

socket_write ( resource socket, string buffer [, int length] )

소켓에 정보를 써넣는 함수로 마지막 인자를 생략하면 buffer의 길이가 자동으로 대입됩니다.

socket_close ( resource socket )

소켓 연결을 끊는다.


2. 소켓 서버 만들기

이제 실전으로 들어가 보겠다. 오늘 만들것은 간단하게 클라이언트가 접속하면 클라이언트의 접속 정보를 출력하고 클라이언트에게 현재 날자와 시간을 전송한후 종료 합니다.

엄밀히 말하면 오늘 만들 소켓 서버는 다중 사용자를 위한 시스템은 아니다. 하지만 오늘은 간단히 소켓의 개념을 집고 넘어가는 의미로 생각하자.

PHP를 CGI형태로 실행하기 위해서 소스코드 상단에

#!/usr/local/bin/php -q
<?php
..
..
..
?>

처럼 프로그래밍을 합니다. 이것은 Perl스크립트나 기타 쉘 스크립트에서 전처리기를 설정하는것과 같은 방법 입니다. -q 옵션은 http protocol 헤더를 제거 하는 옵션입니다.

#!/usr/local/bin/php -q
<?php
define("_IP",    "123.123.123.12");
define("_PORT",  "65000");

$sSock      = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_bind($sSock, _IP, _PORT);
socket_listen($sSock);
while($cSock = socket_accept($sSock))
{
    socket_getpeername($cSock, $addr, $port);
    echo "SERVER >> client connected $addr:$port \n";
    $date = date("Y/m/d H:i:s");
    socket_write($cSock, $date);
    socket_close($cSock);
    echo "SERVER >> client Close.\n";
}
?>

서버는 지속적으로 클라이언트를 기다리는 형태의 모습을 하고 있습니다.


3. 소켓 클라이언트 만들기 와 실행

클라이언트는 서버에 접속을 하고 서버쪽에서 보내온 메시지를 읽은뒤 출력하고 종료합니다.

주의

프로그램상의 아이피는 가상으로 만든 것입니다. 테스트시 적절한 아이피로 변경해 주세요.

#!/home/dimeclub/www/bin/php/php -q
<?php
define("_IP",    "123.123.123.12");
define("_PORT",  "65000");

$sock      = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_connect($sock, _IP, _PORT);
echo "CLIENT >> socket connect to "._IP.":"._PORT."\n";
$date = socket_read($sock, 4096);
echo "CLIENT >> this time is $date \n";
socket_close($sock);
echo "CLIENT >> socket closed.\n";
?>

너무 간단하다고 돌 날아오겠네요. -_-a. 위 두 파일을 server.php, client.php라 저장하고 실행권한을 준뒤 실행해 보도록 하겠습니다.

아래 화면의 #]는 쉘 커맨드 입니다.

#]
#] ll
total 8
-rwxr-xr-x    1 jinoos   jinoos        387 May  7 04:59 client.php
-rwxr-xr-x    1 jinoos   jinoos        495 May  7 04:59 server.php
#]
#] ./server.php &
[1] 23833
#]
#] ./client.php 
SERVER >> client connected 123.123.123.12:45188 
SERVER >> client Close.
CLIENT >> socket connect to 123.123.123.12:65000
CLIENT >> this time is 2003/05/07 04:59:49 
CLIENT >> socket closed.
#]
#] ./client.php 
SERVER >> client connected 123.123.123.12:45358 
SERVER >> client Close.
CLIENT >> socket connect to 123.123.123.12:65000
CLIENT >> this time is 2003/05/07 05:01:03 
CLIENT >> socket closed.
#]
#]

위 내용은 서버프로그램을 백그라운드로 실행하고, 짧은 시간동안 두번 클라이언트로 서버에 접속한 모습입니다. 원하던데로 출력된것을 확인할수 있습니다.

같은 머신 상에서 접속하게 된다면 서버와 클라이언트에서 같은 IP를 출력하게 될것입니다. 그리고 잘보면 클라이언트의 PORT가 변경되었는데 클라이언트의 머신의 경우 일정 대역의 포트중 사용하지 않는 포트를 자동으로 사용하는 것입니다. 이것을 프로그램상으로 조정하는것은 아닙니다. OS에서 자동적으로 할당된것을 사용하는것입니다.


4. 결론

오늘은 간단하게 PHP를 이용해서 소켓함수를 사용하는 것을 해보았습니다. 다음시간에는 PHP의 Process Control Functions 함수들을 이용해서 Fork를 사용한 오늘 보다 좀더 진보된 다중 접속 서버 소켓을 만들어 보겠습니다.

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
MySQL에 보면 DATEDIFF나 TIMEDIFF 함수를 쓰면 두 날짜 사이의 차이를 구할 수 있다.
사실 이 함수를 사용하는 것이 더 편하다.
그런데 이 함수의 사용법을 알면서도 착각을 했는지...
PHP로 그만 다시 만들어 버리고 말았다 -.-;;

function dateDiff($sStartDate, $sEndDate)
{
    $sStartTime = strtotime($sStartDate);
    $sEndTime = strtotime($sEndDate);

    if($sStartTime > $sEndTime)
        return false;

    $sDiffTime = $sEndTime - $sStartTime;

    $aReturnValue['d'] = floor($sDiffTime/60/60/24);
    //$aReturnValue['d'] = $sDiffTime/60/60/24;
    $aReturnValue['H'] = sprintf("%02d", ($sDiffTime/60/60)%24);
    $aReturnValue['i'] = sprintf("%02d", ($sDiffTime/60)%60);

    return $aReturnValue;
}

그냥 다음과 같이 쓰면 배열로 리턴한다.

$aDiffTime = dateDiff('2007-01-01 00:00:00', '2007-01-03 23:00:00');
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret

출처 : TestMaster 님의 블로그

시스템 모니터링이라고 하면 뭔가 복잡하고 어려운 것부터 생각되고 실제로 귀찮은 작업이기도 합니다. 이유있는 문제도 있지만 그렇지 않은 경우도 많습니다. 시스템 에러의 원인을 알 수 없을 때는 참 답답합니다. 그렇다면 그 해결책을 무엇일까요? 스스로 간단한 시스템 모니터링 툴을 만들어 보는 것입니다. SNMP에 대한 기본 지식이 있다면 PHP를 이용해 간단하게 만들 수 있습니다. 리눅스에서 PHP와 SNMP를 이용한 간단한 시스템 모니터링에 대해 알아보겠습니다.

more..


신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret
제가 올리는 팁이 항상 그렇듯이...
실력 좋은 분들은 패쓰해야 하는 허접한 팁입니다.
그점 감안하고 봐 주세요 ^^;;

일반적으로 php 프로그래밍은 길어봐야 수초 내에 끝나는 것이 대부분이다.
하지만, 메일을 보낸다거나 할 경우에는 소스 상단에 set_time_limit(0); 를 추가해서 보내는 경우가 있다.
물론 돈이 많거나, 실력이 뛰어난 프로그래머라면, 좋은 발송기를 사거나, 좋은 프로그램을 짜서 보내면 되지만,
나와 같이 허접한 실력의 프로그래머라면, php로 해결하는 수 밖에 없다 ^^;;;

보통의 경우... 대량 메일을 보내기 위해서는 서버단 설정을 먼저해야 한다.
요즘 나오는 센드메일은 멀티 큐를 지원하고 있고, 큐메일은 예전부터 멀티큐를 지원하기 때문에,
메일 서버 자체에서는 별로 설정할 일이 없다.
만일 메일 서버단의 설정이 궁금하다면, 멀티큐로 검색해 보면 많이 나올 것이다.

오늘 여기서 다루고자 하는 것은...
php 프로그램으로 대량 메일을 어떻게 보내야지만 좋을까 하는 것이다.
사장님의 압력에 몇번의 실패 끝에 알아내게 된 내용을 적어본다.

1. rcpt to를 이용한 방법

처음에 선임자가 짜 놓은 프로그램을 보니 smtp class를 이용해서 보내는 것이었다.
그런데 10만통을 5분에 쏜다고 사장님께서 말씀하시길래 이해가 안가서 소스를 뒤적여 봤더니...
헤더를 조작해서 보내는 것이었다 -.-;;
즉 메일의 rcpt to에다가

aaa@hanmail.com,bbb@hanmail.com,ccc@hanmail.com...........zzz@naver.com

이런식으로 해 놓고, 헤더의 receive에는 그냥 '회원님' 하고 보내는 것이었다.

그러면 받는 사람한테는 rcpt to의 내용이 보이지도 않으면서, php 프로그램 상에서는 메일을 한통만 쏘는 효과가 있었던 것이었다 -.-;;
물론... 센드메일이나 큐메일은 rcpt to에 콤마로 이어놓은 메일 수 만큼 bacrground로 열심히 메일을 뿌리고 있겠지만... ^^;;

하지만 이 방법의 문제점은 header의 to 정보와 rcpt to의 to 정보가 불일치 하기때문에,
대부분의 메일서버가 스팸으로 분류한다는 단점이 있다 -.-;;
결국 보내봐야 소용없는 메일이 되고 만다 -.-;;
따라서 다른 방법을 찾아봐야만 했다.

2. smtp로 직접 접속해서 보내는 방법

smtp로 보내는 방법은 여러가지 설정화 헤더 정보 등을 임의로 입맛에 맞게끔 수정해서 보낼 수 있다.
하지만, 브라우져라면 한번에 한 창을, 실행파일이라면 한번에 한 프로세스만을 띠울 수 밖에 없다.
smtp 프로토콜을 이미 하나의 프로세스가 잡고 있기에, 다른 프로세스는 대기할 수 밖에 없기 때문이다.
따라서 php의 mail() 함수를 사용해서, smtp를 물고 있지 않더라도, MTU에 그냥 메일만 던져주고 빠지는 방식을 쓸 수 밖에 없었다.

3. 콘솔 상에서 보내는 방법

보통 브라우져로 메일을 보내게 되면, 브라우져=>아파치=>php=>MTU 의 단계를 거치게 된다.
또한 브라우져는 http 통신을 하게 되므로 지속적인 연결을 하면서 메일을 발송하는 것에는 조금 불안한 감이 있다.
따라서 php를 binary 버전으로 컴파일 한 후... 아파치와는 독립적으로, perl이나 sh 파일처럼 콘솔 상에서 직접 실행함으로서 조금은 안정적으로 보낼 수 있다.

* 문제점

본인의 경우에는 업체명을 쿼리한 후... 해당 업체에 소속된 회원에게 메일을 발송하는 작업이었다.
메일을 보내는 헤더정보와 메일 내용의 footer 부분에 해당 업체의 정보가 들어가야 하기에 루푸문 안의 쿼리는 어쩔 수 없었다.

업체의 정보와, 회원의 메일 정보를 가져오는 디비쿼리의 경우에는 메일을 보내는 동안 디비 커넥션을 계속 물고 있어야 하기에,
디비 클래스를 조금 수정하여, 해당 정보를 배열로 받고 난 후 접속을 끊어 버리는 형태로 만들었다.
하지만, 이 또한 문제점이 발생하였다.

ex)



위와 같은 소스로 메일을 발송하다보면... 중간에... 다음과 같은 에러가 발생한다



커넥션이 끊어졌다는 것이다. -.-;;
바로 업체 정보를 가져오는 $sComQuery를 실행할 수 없어서 에러가 난 것이다.
그러면서 그 이후의 메일 발송은 바로 stop이 되는 난감한 상태가 발생한 것이다.
그렇다고 해서 connection 타임을 mysql 설정 단에서 늘려주면, 일반 웹서비스로 인해 디비커넥션이 full 되서 디비서버 자체가 죽을 우려가 있었기 때문이다.

조금의 고민 끝에... 커넥션이 끊어 졌으면 pconnect를 써야 겠다 라는 생각에 클래스를 pconnect로 접속하도록 바꿨지만, 이 역시 마찬가지 결과를 가져왔다.

그래서 결국에는 '커넥션 끊어지면, 다시 커넥션 하면 되지 뭐 -.-;;' 라는 생각에...
is_resource 함수를 사용하기로 했다 ^^;;

******* 바꾼 소스... ************


그런데... 다시 생각해 보니 $conn은 원래부터가 resource가 아니였던 것이다. -.-;;
메뉴얼에도 잘 나와 있다시피...



처럼 접속 했을 때 $db_link가 resource인 것이지, new를 통해 생성한 객체는 object 였던 것이다 -.-;;

그래서 결국에는 class에 메쏘드 하나를 추가하기로 했다. -.-;;




그리고 나서 위에 소스도 다음과 같이 수정했다.

******* 최종 소스... *********


아직까지는 잘 돌아가고 있으며, 메일 10만통을 보내는 데 1시간 정도 걸린다.(물론 콘솔을 4개 띄워서 동시에 4개의 프로세스로 돌린 경우이다 ^^;;)
php로 한시간 정도 에러 안나고 돌아가면... 성공한 것 아닌가? ㅋㅋㅋ

어째든... 아무런 에러 없이 계속 돌아가 주기만을 바랄뿐이다 ^^
신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글  9개가 달렸습니다.
  1. is_resource 함수 필요 없네요 -.-;;
    역시나 에러 발생합니다.
    그래서 무조건 커넥션 다시 맺게끔 하고 테스트 해 봤더니, 기존에 커넥션 맺어져 있으면, 다시 안맺네요... ㅋ
    끊어 졌을 경우에만 다시 커넥션을 생성하구요...
    그래서 무조건 커넥션 맺도록 수정했습니다. ^^
  2. 저라면 상단에 메일연락처를 별도파일로 작성한후에 해당 파일을 읽으면서 내용수정하고 메일발송하고 발송결과를 해당파일이나 연관파일에 업데이트 하는 방식을 사용하겠습니다.
  3. 똥파리//이미 스쿨에서 그런 내용들이 나왔는데... 그냥 이전 블로그 폭파되서 다시 올려놓은 팁이에요 ^^
    다시 하게 된다면... 좀더 잘 하게 되겠죠 ㅎㅎ
  4. 비밀댓글입니다
  5. 좋은글 잘 읽었습니다^^
    php를 binary 버전으로 컴파일 한 후 콘솔에서 실행시킨다는 게 어떤건지 궁금합니다. 제가 php입문한지 얼마 안되어서요. 좀 자세히 알려 주실 수 있으실련지요?^^
    • 요즘은 그냥 리눅스에서 설치하면 실치 디렉토리 안에 php 실행 파일이 있더군요.
      고놈을 쉘 실행시키듯이 실행하면 됩니다.
      구글링 해보면 많이 나옵니다 ^^
  6. 포스팅 되어 있는 다중연결 소켓에 나오는 방법을 말씀하시는 거죠?^^
    #!/usr/local/bin/php -q
secret
phpschool의 피곤해 님이 올리신 팁입니다.

***************************************************************************

팁란에 이클립스에서 콘솔상에서 php 실행하는거 보고.. 괜찮다 싶어 적어봅니다.
그래서 에디터플러스에서도 콘솔상으로 출력하는거 적어 봅니다.
큰 팁은 아니지만.. 생각치 못한 분들을 위해..

우선 php.exe 파일이 있어야 윈도우상에서 콘솔로 실행이 가능합니다.
php.net에서 윈도우용 php를 다운 받아서 설치합니다.

그리고 에디터 플러스의 사용자 도구 구성에다 php.exe의 경로를 잡아줍니다.
명령에는 php.exe 파일의 경로를, 인수에는 파일이름, 디렉토리에는 파일디렉토리를 선택해 줍니다.


그리고 아래는 hello world를 콘솔상에서 찍은 겁니다.


에러를 출력하는 화면.. html 태그가 같이 붙어서 출력하는거 말곤.. 괜찮네요..


그럼 왜 콘솔상에서 출력을 하는 것일까??
웹상에서 보면 되지..이런 분이 계실 거라 생각합니다.
php가 웹용에 주로 쓰이다 보니.. 브라우저상에서 확인을 해야 하지만..
class로 생성된 라이브러리(?)나 리턴값을 던지는 함수를 테스트할때 유용할것 같습니다.
ftp로 파일 올리고, 브라우저 띄워서 확인하는 것보다..
코딩후 임의의 데이타를 입력후 에러나 결과값을 테스트하기에 편할거라 생각이 됩니다.
(html과 같이 출력되는 것은 보기에 그렇고, 결과값을 리턴해 주는 함수를 테스트 해 보는데 좋을것 같습니다.)

아래는 time stamp를 date로 찍어주는 클래스를 테스트로 돌린겁니다.



신고
크리에이티브 커먼즈 라이선스
Creative Commons License

WRITTEN BY
체리필터
프로그램 그리고 인생...

받은 트랙백이 없고 , 댓글이 없습니다.
secret