server.php
set_time_limit(0);
define("_IP", {IP});
define("_PORT", {PORT});
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 $key => $sock)
{
// Listen 하고 있는 서버 소켓일 경우
// 새로운 클라이언트의 접속을 의미
echo $sock.'/'.$sSock."\n";
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);
$cmd = $buf;
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:
if(substr($cmd,0,1) == ':'){
msg("client(".$thisSockInfo['port'].") sendmsg : ".substr($cmd,1)."\n");
broadCasting($sockArr,$sock,substr($cmd,1));
}else{
msg("client(".$thisSockInfo['port'].") invalid command $cmd\n");
}
break;
}
}
}
}
}
$i++;
}
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;
}
function broadCasting($socks,$cSock,$msg){
global $sSock;
foreach($socks as $key => $sock){
if($sock != $sSock && $sock != $cSock){
socket_write($sock,$msg);
}
}
}
client.php
define("_IP", {IP});
define("_PORT", {PORT});
$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{
if(substr($stdin,0,1) == ':'){
msg("sendmsg : ".$stdin."\n");
}else{
msg("invalid command (not send). If you want said ':' and your message.: ".$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;
}
단방향 채팅프로그램이다...-_-;
서버에 지정된 명령어에 의해 클라이언트의 메세지를 처리해주는 정도...
다중 클라이언트 접속이 허용되지만
클라이언트간 메세지 교환은 이루어지지 않고
클라이언트 대 서버의 통신만 가능하다.
서버에서 클라이언트의 메세지를 전체 클라이언트에게 뿌려주는
브로드캐스팅 구현이 안됐다...
TODO:
1.서버의 브로드캐스팅을 구현해야 실질적인 다중채팅이 이루어진다.
2.서버에서 임의의 메세지를 전송 하는 기능을 구현해야 한다.
'Programing > PHP' 카테고리의 다른 글
[OSX] Eclipse에서 PHP 로컬 개발/테스트 환경 구축하기 (4) | 2008.08.30 |
---|---|
Enabling PHP and Apache in Leopard (2) | 2008.08.19 |
WAV파일 분석 (0) | 2006.11.10 |
간단한 대화식 프로그램 (0) | 2006.07.24 |
시스템 모니터링 툴 (0) | 2006.07.17 |