일단 Prosilver 템플릿 쓸때

root/styles/prosilver/template/overall_header.html

에디터로 열어

<p>{SITE_DESCRIPTION}</p>
<p><a href="#start_here">{L_SKIP}</a></p>

^ 찾아

 

바로 밑에다 너

<tr><td colspan="2" height="25px" width="100%" class="row"><div align="center">
<!-- PHP -->
$protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
$curURL = $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$currURL = urlencode($curURL);
echo "<iframe src=\"http://www.facebook.com/plugins/like.php?href=$currURL&amp;layout=standard&amp;show_faces=true&amp;width=450&amp;action=like&amp;colorscheme=light\" scrolling=\"no\" frameborder=\"0\" allowTransparency=\"true\" style=\"border:none; overflow:hidden; height: 25px;\"></iframe>";
echo "<fb:like href=\"$currURL\" layout=\"standard\" show_faces=\"true\" height=\"25px\" action=\"like\" colorscheme=\"light\" />";
<!-- ENDPHP -->
</div></td>
</tr>

^ 요거는 기본이고

 

<tr><td colspan="2" height="25px" width="100%" class="row"><div align="center">
<!-- PHP -->
$protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
$curURL = $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
$currURL = urlencode($curURL);
echo "<div id=\"fb-root\"></div><script src=\"http://connect.facebook.net/en_US/all.js#appId=앱아이디넘버&amp;xfbml=1\"></script><fb:like href=\"currURL\" send=\"true\" width=\"450\" show_faces=\"true\" font=\"\"></fb:like>";
<!-- ENDPHP -->
</div></td>
</tr>

^ 이게 좀 수정본 ㅋ

 

Prosilver 템플릿이 아니면?

알아서 너야지. 그걸 왜 나한테 물어봐? 템플릿이 한두개도 아니고.

신고

'Network > PHP' 카테고리의 다른 글

phpBB에 페이스북 Like 버튼 달기  (0) 2011.07.08
lighttpd에 xe 쓸때 rewrite 먹이기  (0) 2011.05.08
xe에 mp4를 jwplayer로 재생하기  (0) 2011.05.08
Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07
url.rewrite = (
    "^/xe/(layouts|m.layouts)/(.+)/(.+)\.html$" =>; "xe/index.php",
 
    "^/xe/(.+)/files/(member_extra_info|attach|cache|faceOff)/(.*)" =>; "xe/files/$2/$3",
    "^/xe/(.+)/(files|modules|common|widgets|widgetStyle|layouts|m.layouts|addons)/(.*)" =>; "xe/$2/$3",
 
    "^(rss|atom)$" =>; "xe/index.php?module=rss&act=$1",
    "^([a-zA-Z0-9_]+)/(rss|atom|api)$" =>; "xe/index.php?mid=$1&act=$2",
    "^/xe/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/(rss|atom|api)$" =>; "xe/index.php?vid=$1&mid=$2&act=$3",
 
    "^/xe/([0-9]+)/(.+)/trackback$" =>; "xe/index.php?document_srl=$1&key=$2&act=trackback",
    "^/xe/([a-zA-Z0-9_]+)/([0-9]+)/(.+)/trackback$" =>; "xe/index.php?vid=$1&document_srl=$2&key=$3&act=trackback",
 
    "^/xe/admin/?$" =>; "xe/index.php?module=admin",
 
    "^/xe/([0-9]+)$" =>; "xe/index.php?document_srl=$1",
 
    "^/xe/([a-zA-Z0-9_]+)/?$" =>; "xe/index.php?mid=$1",
    "^/xe/([a-zA-Z0-9_]+)/([0-9]+)$" =>; "xe/index.php?mid=$1&document_srl=$2",
 
    "^/xe/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$" =>; "xe/index.php?vid=$1&mid=$2",
    "^/xe/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/([0-9]+)$" =>; "xe/index.php?vid=$1&mid=$2&document_srl=$3",
 
    "^/xe/([a-zA-Z0-9_]+)/entry/(.+)$" =>; "xe/index.php?mid=$1&entry=$2",
    "^/xe/([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/entry/(.+)$" =>; "xe/index.php?vid=$1&mid=$2&entry=$3"
)

 

요거를 lighttpd.conf에 집어너

 

우분투는 /etc/lighttpd/lighttpd.conf인데 뭐 어디서 어떻게 쓸건지 모르겠지만 암튼 설정파일 안에다 집어넣는거야

 

/xe/ 말고 딴데 집어넣었으믄 “xe/”로 찾아서 다 바꿔

 

server.modules 안에 “mod_rewrite” 없으면 집어넣고 있으면 앞에 # 붙은거 지워

 

lighttpd 재시작해

 

 

다중계정은 어떻게 하냐고?

 

다중계정은 걍 apache 써.

신고

'Network > PHP' 카테고리의 다른 글

phpBB에 페이스북 Like 버튼 달기  (0) 2011.07.08
lighttpd에 xe 쓸때 rewrite 먹이기  (0) 2011.05.08
xe에 mp4를 jwplayer로 재생하기  (0) 2011.05.08
Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07

flv처럼 mp4 재생시키고 싶으면 따라해

 

 

일단 xe가 들어있는곳에서 그거 처리하는데가 common/js에 있어

 

구버전은 common/tpl/js에 있대 근데 1.4.5 이상 쓸거잖아?

 

신버전은 파일 좀 여러개야 다 바꿔줘야돼

 

common.js랑 xe.js랑 xe.min.js 안에 있어

 

.flv로 찾으면 ~~ if(/\.flv$/i.test(src) || ~~ 요런식으로 나오는게 있을거야

 

|| 뒤에 /\.mp4$/i.test(src) || 요런식으로 붙여

 

관리페이지 들어가

 

캐쉬 정리해

 

mp4 파일도 잘 나올거야

 

 

 

flvplayer는 걍 써도 되는데 최신버전 쓰고싶으면 파일 받아서 common/tpl/images에 집어너

신고

'Network > PHP' 카테고리의 다른 글

phpBB에 페이스북 Like 버튼 달기  (0) 2011.07.08
lighttpd에 xe 쓸때 rewrite 먹이기  (0) 2011.05.08
xe에 mp4를 jwplayer로 재생하기  (0) 2011.05.08
Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07

Source : http://deepbird.tistory.com/368

 

 

간단히 웹어플리케이션을 테스트해볼 웹서버의 필요성을 느낌.

USB에 저장해 간단히 사용할 웹서버를 찾아 봄
http://www.apachefriends.org/en/xampp.html 의 XAMPP Lite를 다운로드 받아 USB에 저장함. 기본팩이 약 192메가, Lite팩이 약 115메가이다.
Apache, MySQL, PHP를 사용할 수 있다.  자세한 사항은 홈페이지 참조
라이트 버전의 경우 Filezilla FTP 서버와 Mercury Mail 이 빠져 있다.

1. 설치

1. 압축파일을 다운로드 받아 압축을 푼뒤 USB에 옮긴다.

2. 폴더를 열어 setup-xampp.bat 파일을 실행한다.
만약 xampp프로그램이 위치한 폴더가 루트디렉토리 바로 아래에 있다면 setup-xampp.bat를 실행할 필요없이 바로 시작할 수 있다.

3. xampp-control.exe 를 시작해 콘트롤패널을 통해 각 서비스를 시작하거나, 배치파일을 이용해 각 서비스를 시작하거나 중지한다.

4. 웹브라우저를 열어 http://localhost/ 나 http://127.0.0.1 로 접속한다.

5. 보안을 위해 http://localhost/security/index.php 에 접속해 mysql의 root 비밀번호를 지정한 뒤 mysql을 재시작한다.

 

2. 설정파일의 위치

· Apache basic configuration: .\xampp\apache\conf\httpd.conf

· Apache SSL: .\xampp\apache\conf\ssl.conf

· Apache Perl (only addon): .\xampp\apache\conf\perl.conf

· Apache Tomcat (only addon): .\xampp\apache\conf\java.conf

· Apache Python (only addon): .\xampp\apache\conf\python.conf

· PHP: .\xampp\apache\bin\php.ini (with the apache actually running php version)

· MySQL: .\xampp\mysql\bin\my.cnf

· phpMyAdmin: .\xampp\phpMyAdmin\config.inc.php

· FileZilla FTP: .\xampp\FileZillaFTP\FileZilla Server.xml

· Mercury Mail basic configuration: .\xampp\MercuryMail\MERCURY.INI

· Sendmail: .\xampp\sendmail\sendmail.ini

 

3. XAMPP에서 사용하는 기본 포트(변경가능)

· http 80 (HTTP)

· https 443 (SSL)

· mysql 3306

· ftp 21

· smtp 25

· pop3 110

· imap 143

· AJP/1.3 8009

· http-alt 8080 (Tomcat Default Port)

 

4. 삭제

압축 파일로 설치 한 경우 삭제는 모든 서비스를 중단한 뒤 설치된 디렉토리를 삭제하면 바로 삭제 된다.

신고

'Network > PHP' 카테고리의 다른 글

lighttpd에 xe 쓸때 rewrite 먹이기  (0) 2011.05.08
xe에 mp4를 jwplayer로 재생하기  (0) 2011.05.08
Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07
PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13

Source : http://www.xpressengine.com/?mid=zb4_tip&search_target=title&search_keyword=4.3.0&document_srl=847097


제로보드를 php 4.3.0 에서 사용할경우 아래와 같은 경고구문이 나타 납니다.

Warning: Unknown(): Your script possibly relies on a session side-effect which existed until PHP 4.2.3. Please be advised that the session extension does not consider global variables as a source of data, unless register_globals is enabled. You can disable this functionality and this warning by setting
session.bug_compat_42 or session.bug_compat_warn to off, respectively. in Unknown on line 0

4.3.0 이상에서는 부작용(side-effect)이 나타 날수 있으니 주의하라...   그냥 경고문구죠

php.ini 파일을 조금만 수정하면 저 경고구문이 안보이게 할 수 있습니다. 그러나 서버관리자는 NO하고 맙니다

이문구가 처음 한번만 나타났다 새로고침하면 없어지고

이건 제로보트가 전역변수선언 사용과 세션과 관련이 깊읍니다.

서버에서 php.ini를 고치는게 어려우신분은 아래와같이 해보시기 바랍니다.

제로보드의 lib.php의 맨윗줄에 <? 바로밑에 넣고 확인하세요

ini_set('register_globals','1');
ini_set('session.bug_compat_42','1');
ini_set('session.bug_compat_warn','0');
ini_set('session.auto_start','1');

이건 php.ini에 설정된것을 현재 로칼에서만 설정이 유지 됩니다.
그런데 ini_set('register_globals','1');
를 설정해도 저같은경우 전역변수 설정은 local에서도 안먹히는데요
그래도 걱정 마세요 제로보드에서 전역변수를 쓸수있게 되었습니다.
글래도 뭔가 값전달이 이상한분

if(count($HTTP_GET_VARS)){extract($HTTP_GET_VARS);} 
if(count($HTTP_POST_VARS)){extract($HTTP_POST_VARS);}
$PHP_SELF=$HTTP_SERVER_VARS[PHP_SELF];
$HTTP_REFERER=$HTTP_SERVER_VARS[HTTP_REFERER];
$REMOTE_ADDR=$HTTP_SERVER_VARS[REMOTE_ADDR];

를 추가하십시요   

신고

'Network > PHP' 카테고리의 다른 글

xe에 mp4를 jwplayer로 재생하기  (0) 2011.05.08
Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07
PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18

<?
  function checkjumin($code) {
    if (eregi("([0-9])([0-9])([0-9])([0-9])([0-3])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])([0-9])",$code,$regs)) {
      $sum = $regs[1]*2+$regs[2]*3+$regs[3]*4+$regs[4]*5+$regs[5]*6+$regs[6]*7+$regs[7]*8+$regs[8]*9+$regs[9]*2+$regs[10]*3+$regs[11]*4+$regs[12]*5;
      $magickey = 11;
      $key = $magickey - ($sum % $magickey);
      return $code.$key;
    } else {
      return "Error";
    }
  }
?>

신고

'Network > PHP' 카테고리의 다른 글

Portable 웹서버 XAMPP  (0) 2011.03.21
php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07
PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18
[PHPSchool] 오늘 본 상품 출력  (0) 2006.08.03

PHP를 이용한 다중 연결 소켓 통신 (1)

이진우

프리랜서
프로그래머

<jinoos@jinoos.com>


차례
1. 소개
1.1. PHP 컴파일 하기
1.2. PHP의 소켓 함수
2. 소켓 서버 만들기
3. 소켓 클라이언트 만들기 와 실행
4. 결론

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

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(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를 사용한 오늘 보다 좀더 진보된 다중 접속 서버 소켓을 만들어 보겠습니다.

 

PHP를 이용한 다중 연결 소켓 통신 (2)


이진우

프리랜서
프로그래머

<jinoos@jinoos.com>





차례
1. 소개
2. SELECT


2.1. socket_select() 함수

3. 프로그램 작성


3.1. 서버 만들기
3.2. 클라이언트 만들기
3.3. 실행하기

4. 결론



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

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(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 requestn");
socket_write($sock, date("Y/m/d H:i:s"));
break;

// 종료
case "quit":
msg("client(".$thisSockInfo['port'].") quit requestn");
socket_write($sock, "quit");
socket_close($sock);
exceptSocket(&$cSock, &$cInfo, $sock);
break;
default:
msg("client(".$thisSockInfo['port'].") invalid command $cmdn");
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를 이용한 다중 연결 소켓 통신을 해보겠습니다.

 

PHP를 이용한 다중 연결 소켓 통신 (3)


이진우

프리랜서
프로그래머

<jinoos@jinoos.com>





차례
1. 소개
2. pcntl_fork() 함수
3. PHP 컴파일 하기
4. 프로그램 작성


4.1. 서버 만들기
4.2. 클라이언트 만들기
4.3. 실행하기

5. 결론



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

문서가 존재하는 모든곳에 답변을 드릴수 없으므로 질문은 홈페이지(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 : $in";
}

// 자식 프로세스
}elseif($pid == 0)
{
for(;$i<10;$i+=2)
{
echo "Child Process $i : $in";
}
}
?>

부모 프로세스는 $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("forkn");
if($pid == -1)
{
msg("fork failedn");
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 requestn");
socket_write($sock, date("Y/m/d H:i:s"));
break;

// 종료
case "quit":
msg("client(".$sockPort.") quit requestn");
socket_write($sock, "quit");
socket_close($sock);
exit;
break;
default:
msg("client(".$sockPort.") invalid command $cmdn");
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과 지금까지 배운 소켓 통신을 가지고 간단한 채팅 클라이언트/서버를 만들어 보겠습니다.

신고

'Network > PHP' 카테고리의 다른 글

php 4.3.0 에서 경고구문 해결  (0) 2011.01.09
PHP 주민등록번호 알고리즘  (0) 2008.03.07
PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18
[PHPSchool] 오늘 본 상품 출력  (0) 2006.08.03
쇼핑몰에 들어가는 오늘 본 상품  (0) 2006.08.03
var n4 = (document.layers)?true:false;
var e4 = (document.all)?true:false;

//숫자만입력(onKeypress='return keyCheckdot(event)')
function keyCheck(e) {
if(n4) var keyValue = e.which
else if(e4) var keyValue = event.keyCode
if (((keyValue >= 48) && (keyValue <= 57)) || keyValue==13) return true;
else return false
}

//숫자및돗트입력(onKeypress='return keyCheckdot(event)')
function keyCheckDot(e) {
if(n4) var keyValue = e.which
else if(e4) var keyValue = event.keyCode
if (((keyValue >= 48) && (keyValue <= 57)) || keyValue==13 || keyValue==46) return true;
else return false
}

//공백제거
function Trim(string) {
for(;string.indexOf(" ")!= -1;){
string=string.replace(" ","")
}
return string;
}

//입력검사
function Exists(input,types) {
if(types) if(!Trim(input.value)) return false;
return true;
}

//영문검사+숫자검사(첫글자는 반드시영문)
function EngNum(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i val = input.value.charAt(i);
if(i == 0) if(!((val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
else if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}

//영문검사+숫자검사
function EngNumAll(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i val = input.value.charAt(i);
if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}

//영문검사+숫자검사+'_'
function EngNumAll2(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i val = input.value.charAt(i);
if(!((val>=0 && val<=9) || (val>='a' && val<='z') || (val>='A' && val<='Z') || val=='_')) return false;
}
return true;
}

//영문검사
function Eng(input,types) {
if(types) if(!Trim(input.value)) return false;
var error_c=0, i, val;
for(i=0;i val = input.value.charAt(i);
if(!((val>='a' && val<='z') || (val>='A' && val<='Z'))) return false;
}
return true;
}

//숫자만입력
/*
function numberonlyinput() {
var ob = event.srcElement;
ob.value = noSplitAndNumberOnly(ob);
return false;
}
*/

//돈(3단위마다 컴마를 붙인다.)
function checkNumber() {
var ob=event.srcElement;
ob.value = filterNum(ob.value);
ob.value = commaSplitAndNumberOnly(ob);
return false;
}

//한정액(일정금액 이상이 되면 올라기지 않게 한다.)
function chkhando(money) {
var ob=event.srcElement;
ob.value = noSplitAndNumberOnly(ob);
if(ob.value > money) ob.value = money;
return false;
}

//이자율(소수점 사용가능)
function checkNumberDot(llen,rlen) {
if(llen == "") llen = 8;
if(rlen == "") rlen = 2;
var ob=event.srcElement;
ob.value = filterNum(ob.value);

spnumber = ob.value.split('.');
if( spnumber.length >= llen && (spnumber[0].length >llen || spnumber[1].length >llen)) {
ob.value = spnumber[0].substring(0,llen) + "." + spnumber[1].substring(0,rlen);
ob.focus();
return false;
}
else if( spnumber[0].length > llen ) {
ob.value = spnumber[0].substring(0,llen) + ".";
ob.focus();
return false;
}
else if(ob.value && spnumber[0].length == 0) {
ob.value = 0 + "." + spnumber[1].substring(0,rlen);
ob.focus();
return false;
}
ob.value = commaSplitAndAllowDot(ob);
return false;
}

//참조함수
function filterNum(str) {
re = /^$|,/g;
return str.replace(re, "");
}

//참조함수(컴마불가)
function commaSplitAndNumberOnly(ob) {

var txtNumber = ' + ob.value;
if (isNaN(txtNumber) || txtNumber.indexOf('.') != -1 ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.value = commaSplitAndNumberOnly(ob);
ob.focus();
return ob.value;
}
else {
var rxSplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])');
var arrNumber = txtNumber.split('.');
arrNumber[0] += '.';
do {
arrNumber[0] = arrNumber[0].replace(rxSplit, '$1,$2');
}
while (rxSplit.test(arrNumber[0]));

if (arrNumber.length > 1) {
return arrNumber.join(');
}
else {
return arrNumber[0].split('.')[0];
}
}
}

//참조함수(컴마가능)
function commaSplitAndAllowDot(ob) {

var txtNumber = ' + ob.value;
if (isNaN(txtNumber) ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.focus();
return ob.value;
}
else {
var rxSplit = new RegExp('([0-9])([0-9][0-9][0-9][,.])');
var arrNumber = txtNumber.split('.');
arrNumber[0] += '.';
do {
arrNumber[0] = arrNumber[0].replace(rxSplit, '$1,$2');
}
while (rxSplit.test(arrNumber[0]));

if (arrNumber.length > 1) {
return arrNumber.join(');
}
else {
return arrNumber[0].split('.')[0];
}
}
}

//숫자만가능
function noSplitAndNumberOnly(ob) {
var txtNumber = ' + ob.value;
if (isNaN(txtNumber) || txtNumber.indexOf('.') != -1 ) {
ob.value = ob.value.substring(0, ob.value.length-1 );
ob.focus();
return ob.value;
}
else return ob.value;
}

//바이트검사
function Byte(input) {
var i, j=0;
for(i=0;i val=escape(input.charAt(i)).length;
if(val== 6) j++;
j++;
}
return j;
}

//팝업메뉴
function popupmenu_show(layername, thislayer, thislayer2) {
thislayerfield.value = thislayer;
thislayerfield2.value = thislayer2;
var obj = document.all[layername];
var _tmpx,_tmpy, marginx, marginy;
_tmpx = event.clientX + parseInt(obj.offsetWidth);
_tmpy = event.clientY + parseInt(obj.offsetHeight);
_marginx = document.body.clientWidth - _tmpx;
_marginy = document.body.clientHeight - _tmpy ;
if(_marginx < 0) _tmpx = event.clientX + document.body.scrollLeft + _marginx ;
else _tmpx = event.clientX + document.body.scrollLeft ;
if(_marginy < 0) _tmpy = event.clientY + document.body.scrollTop + _marginy + 20;
else _tmpy = event.clientY + document.body.scrollTop ;
obj.style.posLeft = _tmpx - 5;
obj.style.posTop = _tmpy;

layer_set_visible(obj, true);
layer_set_pos(obj, event.clientX, event.clientY);
}
function layer_set_visible(obj, flag) {
if (navigator.appName.indexOf('Netscape', 0) != -1) obj.visibility = flag ? 'show' : 'hide';
else obj.style.visibility = flag ? 'visible' : 'hidden';
}
function layer_set_pos(obj, x, y) {
if (navigator.appName.indexOf('Netscape', 0) != -1) {
obj.left = x;
obj.top = y;
} else {
obj.style.pixelLeft = x + document.body.scrollLeft;
obj.style.pixelTop = y + document.body.scrollTop;
}
}

//페이지이동
function move(url) {
location.href = url;
}

//닫기
function toclose() {
self.close();
}

//위치변경
function winsize(w,h,l,t) {
if(window.opener) resizeTo(w,h);
}

//포커스위치
function formfocus(form) {
var len = form.elements.length;
for(i=0;i if((form.elements[i].type == "text" || form.elements[i].type == "password") && Trim(form.elements[i].value) == "") {
form.elements[i].value = "";
form.elements[i].focus();
break;
}
}
}

// 날짜,시간 format 함수 = php의 date()
function date(arg_format, arg_date) {
if(!arg_date) arg_date = new Date();

var M = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
var F = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
var K = new Array("일","월","화","수","목","금","토");
var k = new Array("日","月","火","水","木","金","土");
var D = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
var l = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
var o = new Array("전","후");
var O = new Array("오전","오후");
var a = new Array("am","pm");
var A = new Array("AM","PM");

var org_year = arg_date.getFullYear();
var org_month = arg_date.getMonth();
var org_date = arg_date.getDate();
var org_wday = arg_date.getDay();
var org_hour = arg_date.getHours();
var org_minute = arg_date.getMinutes();
var org_second = arg_date.getSeconds();
var hour = org_hour % 12; hour = (hour) ? hour : 12;
var ampm = Math.floor(org_hour / 12);

var value = new Array();
value["Y"] = org_year;
value["y"] = String(org_year).substr(2,2);
value["m"] = String(org_month+1).replace(/^([0-9])$/,"0$1");
value["n"] = org_month+1;
value["d"] = String(org_date).replace(/^([0-9])$/,"0$1");
value["j"] = org_date;
value["w"] = org_wday;
value["H"] = String(org_hour).replace(/^([0-9])$/,"0$1");
value["G"] = org_hour;
value["h"] = String(hour).replace(/^([0-9])$/,"0$1");
value["g"] = hour;
value["i"] = String(org_minute).replace(/^([0-9])$/,"0$1");
value["s"] = String(org_second).replace(/^([0-9])$/,"0$1");
value["t"] = (new Date(org_year, org_month+1, 1) - new Date(org_year, org_month, 1)) / 86400000;
value["z"] = (new Date(org_year, org_month, org_date) - new Date(org_year, 0, 1)) / 86400000;
value["L"] = ((new Date(org_year, 2, 1) - new Date(org_year, 1, 1)) / 86400000) - 28;
value["M"] = M[org_month];
value["F"] = F[org_month];
value["K"] = K[org_wday];
value["k"] = k[org_wday];
value["D"] = D[org_wday];
value["l"] = l[org_wday];
value["o"] = o[ampm];
value["O"] = O[ampm];
value["a"] = a[ampm];
value["A"] = A[ampm];

var str = "";
var tag = 0;
for(i=0;i var chr = arg_format.charAt(i);
switch(chr) {
case "<" : tag++; break;
case ">" : tag--; break;
}
if(tag || value[chr]==null) str += chr; else str += value[chr];
}

return str;
}

// 해상도에 맞는 크기 사용
function screensize() {
self.moveTo(0,0);
self.resizeTo(screen.availWidth,screen.availHeight);
}

// 주민등록번호체크( 입력폼 1개)
function check_jumin(jumin) {
var weight = "234567892345"; // 자리수 weight 지정
var val = jumin.replace("-",""); // "-"(하이픈) 제거
var sum = 0;

if(val.length != 13) { return false; }

for(i=0;i<12;i++) {
sum += parseInt(val.charAt(i)) * parseInt(weight.charAt(i));
}

var result = (11 - (sum % 11)) % 10;
var check_val = parseInt(val.charAt(12));

if(result != check_val) { return false; }
return true;
}

// 주민등록번호체크( 입력폼 2개)
function check_jumin2(input, input2) {
input.value=Trim(input.value);
input2.value=Trim(input2.value);
var left_j=input.value;
var right_j=input2.value;
if(input.value.length != 6) {
alert('주민등록번호를 정확히 입력하세요.');
input.focus();
return true;
}
if(right_j.length != 7) {
alert('주민등록번호를 정확히 입력하세요.');
input2.focus();
return true;
}
var i2=0;
for(var i=0;i var temp=left_j.substring(i,i+1);
if(temp<0 || temp>9) i2++;
}
if((left_j== ') || (i2 != 0)) {
alert('주민등록번호가 잘못 입력되었습니다.');
j_left.focus();
return true;
}
var i3=0;
for(var i=0;i var temp=right_j.substring(i,i+1);
if (temp<0 || temp>9) i3++;
}
if((right_j== ') || (i3 != 0)) {
alert('주민등록번호가 잘못 입력되었습니다.');
input2.focus();
return true;
}
var l1=left_j.substring(0,1);
var l2=left_j.substring(1,2);
var l3=left_j.substring(2,3);
var l4=left_j.substring(3,4);
var l5=left_j.substring(4,5);
var l6=left_j.substring(5,6);
var hap=l1*2+l2*3+l3*4+l4*5+l5*6+l6*7;
var r1=right_j.substring(0,1);
var r2=right_j.substring(1,2);
var r3=right_j.substring(2,3);
var r4=right_j.substring(3,4);
var r5=right_j.substring(4,5);
var r6=right_j.substring(5,6);
var r7=right_j.substring(6,7);
hap=hap+r1*8+r2*9+r3*2+r4*3+r5*4+r6*5;
hap=hap%11;
hap=11-hap;
hap=hap%10;
if(hap != r7) {
alert('주민등록번호가 잘못 입력되었습니다.');
input2.focus();
return true;
}
return false;
}

// 비밀번호 체크
function check_passwd(input, input2, min) {
if(!input.value) {
alert('비밀번호를 입력해 주십시오.');
input.focus();
return false;
}
else if(BYTE(input.value) < min) {
alert('비밀번호의 길이가 너무 짧습니다.');
input.focus();
input.value=';
input2.value=';
return false;
}
else if(!input2.value) {
alert('확인비밀번호를 입력해 주십시오.');
input2.focus();
return false;
}
else if(input.value != input2.value) {
alert('비밀번호가 서로 다르게 입력되었습니다.');
input2.value=';
input2.focus();
return false;
}
else return true;
}

//콤마 넣기(정수만 해당)
function comma(val) {
val = get_number(val);
if(val.length <= 3) return val;

var loop = Math.ceil(val.length / 3);
var offset = val.length % 3;

if(offset==0) offset = 3;
var ret = val.substring(0, offset);

for(i=1;i ret += "," + val.substring(offset, offset+3);
offset += 3;
}
return ret;
}

//문자열에서 숫자만 가져가기
function get_number(str) {
var val = str;
var temp = "";
var num = "";

for(i=0; i temp = val.charAt(i);
if(temp >= "0" && temp <= "9") num += temp;
}
return num;
}

//주민등록번호를 나이로 변환
function agechange(lno,rno) {
var refArray = new Array(18,19,19,20,20,16,16,17,17,18);
var refyy = rno.substring(0,1);
var refno = lno.substring(0,2);
var biryear = refArray[refyy] * 100 + eval(refno);

var nowDate = new Date();
var nowyear = nowDate.getYear();
return nowyear - biryear + 1;
}

//레디오박스 체크검사
function radio_chk(input, msg) {
var len = input.length;
for(var i=0;i alert(msg);
return false;
}

//셀렉트박스 체크검사
function select_chk(input, msg) {
if(input[0].selected == true) {
alert(msg);
return false;
}
return true;
}

//새창띄우기
function open_window(url, target, w, h, s) {
if(s) s = 'yes';
else s = 'no';
var its = window.open(url,target,'width='+w+',height='+h+',top=0,left=0,scrollbars='+s);
its.focus();
}
//-->

//셀렉트
function optionlist($optionlist, $getvalue="", $keyfield="key", $valuefield="value") {
foreach($optionlist as $key => $value) {
if($getvalue && $getvalue == ${$keyfield}) $chk = "selected";
else $chk = "";
echo "{${$valuefield}}";
}
echo "n";
}

//셀렉티드
function selected($checkkey, $getvalue="") {
echo "value='$checkkey'";
if($getvalue && $checkkey == $getvalue) echo " selected";
}

//체크드
function checked($checkkey, $getvalue="") {
echo "value='$getvalue'";
if($getvalue && $checkkey == $getvalue) echo " checked";
}

//주민번호 검사
function RegiNum($reginum) {
$weight = '234567892345'; // 자리수 weight 지정
$len = strlen($reginum);
$sum = 0;

if ($len <> 13) { return false; }

for ($i = 0; $i < 12; $i++) {
$sum = $sum + (substr($reginum,$i,1) * substr($weight,$i,1));
}

$rst = $sum%11;
$result = 11 - $rst;

if ($result == 10) {$result = 0;}
else if ($result == 11) {$result = 1;}

$jumin = substr($reginum,12,1);

if ($result <> $jumin) {return false;}
return true;
}

//사업자번호 검사
function comRegiNum($reginum) {
$weight = '137137135'; // 자리수 weight 지정
$len = strlen($reginum);
$sum = 0;

if ($len <> 10) { return false; }

for ($i = 0; $i < 9; $i++) {
$sum = $sum + (substr($reginum,$i,1) * substr($weight,$i,1));
}
$sum = $sum + ((substr($reginum,8,1)*5)/10);
$rst = $sum%10;

if ($rst == 0) {$result = 0;}
else {$result = 10 - $rst;}

$saub = substr($reginum,9,1);

if ($result <> $saub) {return false;}
return true;
}

//글자르기
function cut_str($msg,$cut_size,$tail="...") {
if($cut_size <= 0) return $msg;
$msg = strip_tags($msg);
$msg = str_replace("&mp;quot;",""",$msg);
if(strlen($msg) <= $cut_size) return $msg;

for($i=0;$i<$cut_size;$i++) if(ord($msg[$i])>127) $han++; else $eng++;
if($han%2) $han--;

$cut_size = $han + $eng;

$tmp = substr($msg,0,$cut_size);
$tmp .= $tail;
return $tmp;
}

// 모든한글의 글자를 출력
function hangul_code() {
$count = 0;
for($i = 0x81; $i <= 0xC8; $i++) {
for($j = 0x00; $j <= 0xFE; $j++) {
if(($j >= 0x00 && $j <= 0x40) || ($j >= 0x5B && $j <= 0x60) || ($j >= 0x7B && $j <= 0x80) || ($j >= 0x00 && $j <= 0x40) ||
(($i >= 0xA1 && $i <=0xAF) && ($j >= 0xA1 && $j <= 0xFE)) || ($i == 0xC6 && ($j >= 0x53 && $j <= 0xA0)) ||
($i >= 0xC7 && ($j >= 0x41 && $j <= 0xA0))) continue;
echo chr($i).chr($j)." ";
$count++;
}
}
echo $count;
}

// 한글검사
function is_han($str) {
if(strlen($str) != 2) return false;

$i = ord ($str[0]);
$j = ord ($str[1]);

if($i < 0x81 || $i > 0xC8 || $j > 0xFE || ($j >= 0x00 && $j <= 0x40) || ($j >= 0x5B && $j <= 0x60) || ($j >= 0x7B && $j <= 0x80) ||
($j >= 0x00 && $j <= 0x40) || (($i >= 0xA1 && $i <=0xAF) && ($j >= 0xA1 && $j <= 0xFE)) ||
($i == 0xC6 && ($j >= 0x53 && $j <= 0xA0)) || ($i >= 0xC7 && ($j >= 0x41 && $j <= 0xA0))) return false;
else return true;
}

// 랜덤값 생성
function random_string($length) {
$randomcode = array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'A', 'B', 'C', 'd', 'E', 'F', 'G', 'H', 'x', 'J',
'K', 'b', 'M', 'N', 'y', 'P', 'r', 'R', 'S', 'T',
'u', 'V', 'W', 'X', 'Y', 'Z');
mt_srand((double)microtime()*1000000);
for($i=1;$i<=$length;$i++) $Rstring .= $randomcode[mt_rand(1, 36)];
return $Rstring;
}

// 디렉토리 리스트
function DirList($path="./") {
$path = opendir($path);
while($list = readdir($path)) if($list != "." && $list != "..") $Arraydir[] = $list;
closedir($path);
return $Arraydir;
}

// 15자리의 유일한 숫자값 만들기
function uniquenumber() {
$temparray = explode(" ", microtime());
$temparray2 = substr($temparray[0],2,5);
$number =$temparray[1].$temparray2;
return $number;
}

// 파일이름과 확장자 분리
function ExplodeFile($filename) {
$filename = strtolower($filename);
$elements = explode('.',$filename);
$elemcnt = count($elements)-1;
if(count($elements)==1) $ext = ';
else $ext = $elements[$elemcnt];
unset($elements[$elemcnt]);
$fname = implode($elements,');

$fileinfo["name"] = $fname;
$fileinfo["ext"] = $ext;
return $fileinfo;
}

// 그림확장자
function ImageType($filename) {
$webimg = explodefile($filename);

$webext = $webimg["ext"];
$defineexp = array("gif","jpg","png");

$count = count($defineexp);

for($i=0;$i<$count;$i++) {
if($defineexp[$i] == $webext) return true;
}
return false;
}

// 유닉스날짜 포맷
function date_format($unixtime,$format="Y.m.d",$empty=" ") {
if($unixtime) return date($format, $unixtime);
else return $empty;
}

//YYYY-MM-DD 형식을 유닉스 타임으로
function unix_format($times, $operator="-", $type=true) {
if($type == true) {
$times = trim($times);
$arry = explode($operator,$times);
if(count($arry) != 3) return date_format(0);
$mktime = mktime(0,0,0,$arry[1],$arry[2],$arry[0]);
return date("U", $mktime);
} else {
$formats = "Y{$operator}m{$operator}d";
return date($formats, $times);
}
}

// 주민등록번호 포맷
function jumin_format($juminno, $cutno=3, $des="x", $empty=" ") {
$juminno = str_replace("-","",$juminno);
if(strlen($juminno) != 13) return $empty;
for($i=0;$i<$cutno;$i++) $x .= $des;
$juminno = substr($juminno,0,13-$cutno).$x;
$juminno = substr($juminno,0,6)."-".substr($juminno,6);
return $juminno;
}

// 홈페이지 포맷
function url_format($url, $ltype=false, $title=false, $other="", $htype="http://", $empty=" ") {
$url = eregi_replace("http://","",trim($url));
if($url) $url = $htype.$url;
else return $empty;

if($title) $turl = $title;
else $turl = $url;

if($ltype) return "{$turl}";
else return $url;
}

// 전송값 초기화
function post_format($str, $type) {
switch($type) {
case "url":
$str = trim($str);
$str = eregi_replace("http://","",$str);
break;
case "num":
$str = trim($str);
$str = str_replace(",","",$str);
break;
}
return $str;
}

// 이메일 포맷
function mail_format($email, $ltype=false, $title=false, $empty=" ") {
$email = trim($email);
$title = trim($title);

if(!$email && !$title) return $empty;
else if(!$email) return $title;

if($title) $temail = $title;
else $temail = $email;

if($ltype) return "{$temail}";
else return $email;
}

// 전화번호 포맷
function tel_format($num1, $num2, $num3, $format="-", $empty=" ") {
$num1 = trim($num1);
$num2 = trim($num2);
$num3 = trim($num3);

if(!$num1) $num1 = "02";

if($num2 && $num3) return $num1.$format.$num2.$format.$num3;
else return $empty;
}

// 문자 포맷
function text_format($str, $empty=" ") {
$str = trim($str);
if($str) return $str;
else return $empty;
}

// 새창띄우기
function win_format($title, $url, $target, $width, $height, $scrollbars=1, $empty) {
$title = text_format($title, $empty);
? return "&lt;a xhref='#' onclick="open_window('{$url}', '{$target}', {$width}, {$height}, {$scrollbars})"&gt;{$title}&lt;/a&gt;"; }

// 나이(주민등록번호를 이용)
function AGE_jumin($lno,$rno) {
$refArray = Array(18,19,19,20,20,16,16,17,17,18);
$refyy = substr($rno,0,1);

$biryear = $refArray[$refyy] * 100 + substr($lno,0,2);
$nowyear = date("Y");
return $nowyear - $biryear + 1;
}

// URL 존재확인
function URL_exists($url) {
$url = str_replace("http://", "", $url);
list($domain, $file) = explode("/", $url, 2); // 도메인부분과 주소부분으로 나눕니다.
$fid = fsockopen($domain, 80); // 도메인을 오픈합니다.
fputs($fid, "GET /$file HTTP/1.0rnHost: $domainrnrn"); // 파일 정보를 얻습니다.
$gets = fgets($fid, 128);
fclose($fid);

if(ereg("200 OK", $gets)) return TRUE;
else return FALSE;
}

// 조사 꾸미기
$array = "뵤 벼 뱌 배 베 보 버 바 비 뷰 부 브 뱨 볘 봐 봬 붜 붸 뵈 뷔 븨 뾰 뼈 뺘 빼 뻬 뽀 뻐 빠 삐 쀼 뿌 쁘 뺴 뼤 뽜 뽸 뿨 쀄 뾔 쀠 쁴 죠 져 쟈 재 제 조 저 자 지 쥬 주 즈 쟤 졔 좌 좨 줘 줴 죄 쥐 즤 쬬 쪄 쨔 째 쩨 쪼 쩌 짜 찌 쮸 쭈 쯔 쪠 쪠 쫘 쫴 쭤 쮀 쬐 쮜 쯰 됴 뎌 댜 대 데 도 더 다 디 듀 두 드 댸 뎨 돠 돼 둬 뒈 되 뒤 듸 뚀 뗘 땨 때 떼 또 떠 따 띠 뜌 뚜 뜨 떄 뗴 똬 뙈 뚸 뛔 뙤 뛰 띄 교 겨 갸 개 게 고 거 가 기 규 구 그 걔 계 과 괘 궈 궤 괴 귀 긔 꾜 껴 꺄 깨 께 꼬 꺼 까 끼 뀨 꾸 끄 꺠 꼐 꽈 꽤 꿔 꿰 꾀 뀌 끠 쇼 셔 샤 새 세 소 서 사 시 슈 수 스 섀 셰 솨 쇄 숴 쉐 쇠 쉬 싀 쑈 쎠 쌰 쌔 쎄 쏘 써 싸 씨 쓔 쑤 쓰 썌 쎼 쏴 쐐 쒀 쒜 쐬 쒸 씌 묘 며 먀 매 메 모 머 마 미 뮤 무 므 먜 몌 뫄 뫠 뭐 뭬 뫼 뮈 믜 뇨 녀 냐 내 네 노 너 나 니 뉴 누 느 냬 녜 놔 놰 눠 눼 뇌 뉘 늬 요 여 야 애 에 오 어 아 이 유 우 으 얘 예 와 왜 워 웨 외 위 의 료 려 랴 래 레 로 러 라 리 류 루 르 럐 례 롸 뢔 뤄 뤠 뢰 뤼 릐 효 혀 햐 해 헤 호 허 하 히 휴 후 흐 햬 혜 화 홰 훠 훼 회 휘 희 쿄 켜 캬 캐 케 코 커 카 키 큐 쿠 크 컈 켸 콰 쾌 쿼 퀘 쾨 퀴 킈 툐 텨 탸 태 테 토 터 타 티 튜 투 트 턔 톄 톼 퇘 퉈 퉤 퇴 튀 틔 쵸 쳐 챠 채 체 초 처 차 치 츄 추 츠 챼 쳬 촤 쵀 춰 췌 최 취 츼 표 펴 퍄 패 페 포 퍼 파 피 퓨 푸 프 퍠 폐 퐈 퐤 풔 풰 푀 퓌 픠";
function lastCon($str) {
global $array;
if(ord($str[strlen($str)-1]) < 128) return false;
$str = substr($str, strlen($str)-2);
if(strstr($array, $str)) return false;
return true;
}
function ul_rul($str) {
return $str.(lastCon($str) ? "을" : "를");
}
function gwa_wa($str) {
return $str.(lastCon($str) ? "과" : "와");
}
function un_num($str) {
return $str.(lastCon($str) ? "은" : "는");
}
function i_ga($str) {
return $str.(lastCon($str) ? "이" : "가");
}

// 도메인 또는 문서가 존재하는지 검사
function exists_url($url, $port="80") {
$fp = @fsockopen($url, $port);
if($fp) return true;
else return false;
}

// 숫자를 한글로 바꾸기
function numtokor($num) {
$text =';
$d_symbol = array('4' => "만", '8' => "억", '12' => "조", '16' => "경", '20' => "해", '24' => "시", '28' => "양", '32' => "구", '36' => "간", '40' => "정", '44' => "재", '48' => "극", '52' => "항하사", '56' => "아승지", '60' => "나유타", '64' => "불가사의", '68' => "무량대수");
$p_symbol = array('0' => "", '1' => "십", '2' => "백", '3' => "천");
$t_symbol = array('0' => "", '1' => "일", '2' => "이", '3' => "삼", '4' => "사", '5' => "오", '6' => "육", '7' => "칠", '8' => "팔", '9' => "구");

if(substr($num,0,1) == '-') {
$num = substr($num ,1);
$text .= '마이너스';
}
$length_of_num = strlen($num);
if($length_of_num > 72) {
$text = "존재할 수 없는 수치 입니다.";
} else {
//실행
for ($k=0; $k< $length_of_num; $k++) {
$striped_value = substr($num, $k, 1);
$text .= $t_symbol[$striped_value];
$power_value = ($length_of_num - $k -1) % 4;
if ($striped_value <> 0) $text .= $p_symbol[$power_value];
if ($power_value == 0) $text .= $d_symbol[$length_of_num - $k -1];
}
}
return $text;
}

//검색쿼리작성
function querystring($query) {
if($query) {
$queryarray = explode("&", $query);
$count = count($queryarray);

foreach($queryarray as $key => $value) {
$array2st = explode("=", $value);
if($array2st[1]) {
if($querystring) $querystring .= "&".$value;
else $querystring = $value;
}
}

return $querystring;
}
else return "";
}

//페이징
function pagelist($tables, $nowpage, $primarykey , $chartline, $chartpage, $wheres="", $findquery="", $others="", $orders="", $urlquery="", $lastopt=true, $allopt=true, $firstbutton="[처음]", $prebutton="[이전]", $nextbutton="[다음]",$lastbutton="[끝]") {

if($wheres) $wheres = " where {$wheres} ";
if($others) $wheres .= " and {$others} ";

if(!$chartline) $chartline = 10;
if(!$chartpage) $chartpage = 10;

if(intval($nowpage) == 0) $nowpage = 1;
if(intval($nowstep) == 0) $nowstep = 1;

##마지막버튼 유무 체크
if($lastopt) {
$query = "select count(*) count from {$tables} {$wheres} {$others} {$findquery}";
$result = mysql_query($query);
$total = mysql_fetch_object($result);
#총카운트 $total->count;
}

##총검색수
if($allopt) {
$query = "select count(*) count from {$tables} {$wheres}";
$result = mysql_query($query);
$all = mysql_fetch_object($result);
#총검색수 $all->count;
}

##설정값계산
$nowstep = ceil($nowpage/$chartpage);
if($lastopt) {
$allstep = ceil($total->count/($chartpage*$chartline));
$allpage = ceil($total->count/$chartline);
}
$startpage = 1 + ($nowstep-1) * $chartpage;
$endpage = $startpage + $chartpage - 1;

if($lastopt && $endpage > $allpage) $endpage = $allpage;

##다음버튼 유무 체크
$nextline = $nowstep * $chartline * $chartpage;
$nextlimitquery = " limit {$nextline}, 1";
$query = "select {$primarykey} from {$tables} {$wheres} {$others} {$findquery} {$nextlimitquery}";
$result = mysql_query($query);
$nextok = mysql_affected_rows();

##처음버튼 및 이전버튼
if($nowstep > 1) {
$fir = " {$firstbutton} ";
$prepage = $startpage - $chartpage;
$pre = " {$prebutton} ";
} else {
$fir = " {$firstbutton} ";
$pre = " {$prebutton} ";
}

##NEXT 버튼 활성화
if($nextok) {
$nextpage = $endpage + 1;
$next = " {$nextbutton} ";
} else {
$next = " {$nextbutton} ";
}

##중간페이지
for($i=$startpage;$i<=$endpage;$i++) {
if($i == $nowpage) $pagelist .= " $i ";
else $pagelist .= " $i ";
}

##끝페이지
if($lastopt && $allstep > $nowstep) {
$lastpage = $allpage;
$last = " {$lastbutton} ";
} else {
$last = " {$lastbutton} ";
}

$firstlimit = 0 + ($nowpage-1) * $chartline;
$limitquery = " limit {$firstlimit}, {$chartline}";
$query = "select * from {$tables} {$wheres} {$others} {$findquery} {$orders} {$limitquery}";
$result = mysql_query($query);
while($fetch = mysql_fetch_array($result)) $get[] = $fetch;

$get[0]["count"] = count($get);
$get[0]["page"] = $fir.$pre." [ ".$pagelist." ] ".$next.$last;
if($lastopt) $get[0]["total"] = $total->count;
if($allopt) $get[0]["allto"] = $all->count;

return $get;

}

//업로드
function file_upload($upfile,$upfile_name,$upfile_size,$dir,$newfilename) {
if($upfile_size) {

$is_file = is_file("{$dir}/{$newfilename}");
if($is_file) unlink("{$dir}/{$newfilename}");

move_uploaded_file($upfile, "{$dir}/{$newfilename}");
chmod("{$dir}/{$newfilename}", 0644);

return true;

} else return false;
}

//현재디렉토리
function nowdir() {
global $DOCUMENT_ROOT;
global $PHP_SELF;
$getdir = pathinfo($DOCUMENT_ROOT.$PHP_SELF);
return $getdir["dirname"];
}
신고

'Network > PHP' 카테고리의 다른 글

PHP 주민등록번호 알고리즘  (0) 2008.03.07
PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18
[PHPSchool] 오늘 본 상품 출력  (0) 2006.08.03
쇼핑몰에 들어가는 오늘 본 상품  (0) 2006.08.03
PHP를 이용한 개발 기간의 단축  (0) 2006.06.04





실직자 무료 수강으로 프로그램 아주 쬐꼼 배우고서 쇼핑몰을 하나 운영중입니다..
근데 오늘 상품이 구현된 다른 쇼핑몰을 보니깐 저두 해보고 싶군요..근데 쿠키로 저장을 해서 상품이 10개든 20개든 중복되지 않게하는 방법을 통 모르겠네요..
며칠을 책을 뒤지며 인터넷을 뒤져봐도 제 능력으론 한계가 있습니다.
제가 배열을 잘 이해를 못하고 있거든요.. ㅠ.ㅠ고수님들 부탁좀 드립니다..
아주 무식한 초보에게 설명한다 생각하시고 쉽게 풀어서 설명 주시면 감사하겠습니다..











배열로 한다면....
$상품번호(고유번호)를 키값으로 갖는 배열을 만들어 쿠키로 저장하면 될 듯 싶은데요.
아님 in_array 나 array_search로 중복 검사를 하면 될 듯 싶구요.
또는 정규식 등을 이용하는 방법도 괜찮을 듯 싶네요.
$쿠키값 = ",상품번호1,상품번호2,상품번호3,상품번호4";
if(ereg($쿠키값, ",신규상품번호") !== false){
$쿠키값 .=",신규상품번호";
}

신고

'Network > PHP' 카테고리의 다른 글

PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18
[PHPSchool] 오늘 본 상품 출력  (0) 2006.08.03
쇼핑몰에 들어가는 오늘 본 상품  (0) 2006.08.03
PHP를 이용한 개발 기간의 단축  (0) 2006.06.04
[PHPSchool] 일본어 송신 관련  (0) 2006.06.03
String[] cookie_list = {"clist1", "clist2", "clist3", "clist4", "clist5"}; // HashMap에 들어갈 key name
Cookie[] cookies = request.getCookies(); // 현재 있는 쿠키를 받아서
HashMap map = new HashMap();
boolean check = false; // 중복확인체크for(int i=0; i map.put(cookie_list[i], cookies[i].getValue()); // map에 대입
}

if(!map.containsValue(request.getParameter("idx"))){ // 중복숫자 x
for(int i=map.size()-1; i>0 && i<=cookie_list.length; i--){ // 마지막부터
if(i!=cookies.length){ // 맨끝은 제외
map.remove(cookie_list[i]); // 한칸씩 뒤로
map.put(cookie_list[i], (String)map.get(cookie_list[i-1])); // 이동
}
}
} else{ // 중복숫자 o
for(int i=map.size()-1; i>0 && i<=cookie_list.length; i--){ // 마지막부터
if(i!=cookies.length){ // 맨끝은 제외
if(((String)map.get(cookie_list[i])).equals(request.getParameter("idx"))){ // 중복숫자체크
check = true; // 확인 후
}
if(check){ // 중복이 발견 된 곳부터
map.remove(cookie_list[i]); // 한칸씩 뒤로
map.put(cookie_list[i], (String)map.get(cookie_list[i-1])); // 이동
}
}
}
}
map.put(cookie_list[0], request.getParameter("idx")); // 맨 앞에 현재 본 상품 삽입

for(int i=0; i Cookie cookie = new Cookie(cookie_list[i], (String)map.get(cookie_list[i])); // 쿠키굽기
response.addCookie(cookie);
}

for(int i=0; i out.println(cookies[i].getName() + ": " + cookies[i].getValue()+"
"); // 쿠키확인
}
신고

'Network > PHP' 카테고리의 다른 글

PHP를 이용한 다중 연결 소켓 통신  (0) 2008.02.13
PHP 함수  (0) 2006.08.18
[PHPSchool] 오늘 본 상품 출력  (0) 2006.08.03
쇼핑몰에 들어가는 오늘 본 상품  (0) 2006.08.03
PHP를 이용한 개발 기간의 단축  (0) 2006.06.04
[PHPSchool] 일본어 송신 관련  (0) 2006.06.03

+ Recent posts