Files
wy/ZeedFramework/library/3rd/soar/1.0/basic/sock.inc
2026-01-07 11:40:41 +08:00

227 lines
6.8 KiB
PHP

<?php
class sock
{
const MSG_SIZE_SIZE=6;
private static $RECV=0;
private static $SEND=1;
private static $ACCEPT=2;
private function wrap(&$msg)
{/*{{{*/
$fmt=sprintf("%%0%dX", self::MSG_SIZE_SIZE);
return sprintf($fmt, strlen($msg)).$msg;
}/*}}}*/
private function wait($socktype, $sock, &$timeout)
{/*{{{*/
if($timeout < 0)
return true;
switch($socktype)
{
case self::$RECV:
case self::$ACCEPT:
$read=array($sock);
$write=null;
break;
case self::$SEND:
$read=null;
$write=array($sock);
break;
}
$now=gettimeofday();
$begin=$now['sec'];
$to=$timeout;
$num=socket_select($read, $write, $exp=null, $to, 0);
if($num === false)
return false;
if($num == 0)
{
$timeout=0;
return false;
}
$now=gettimeofday();
$used=$now['sec']-$begin;
$timeout=$to > $used ? $to-$used : 0;
return true;
}/*}}}*/
public function listen($port)
{/*{{{*/
$sock=socket_create(AF_INET, SOCK_STREAM, 0);
if(@socket_bind($sock, "0.0.0.0", $port) == false)
{
$error=socket_last_error();
errlog::add("%s|%s: socket_bind fail, err:%d %s",
basename(__FILE__), __METHOD__,
$error, socket_strerror($error));
return false;
}
if(@socket_listen($sock) == false)
{
$error=socket_last_error();
errlog::add("%s|%s: socket_listen fail, err:%d %s",
basename(__FILE__), __METHOD__,
$error, socket_strerror($error));
return false;
}
return $sock;
}/*}}}*/
public function accept($sock, &$timeout)
{/*{{{*/
if(self::wait(self::$ACCEPT, $sock, $timeout) == false)
{
// errlog::add("%s|%s: accept timeout",
// basename(__FILE__), __METHOD__);
return false;
}
$new_sock=socket_accept($sock);
if($new_sock === false)
{
errlog::add("%s|%s: socket_accept fail, err:%d",
basename(__FILE__), __METHOD__, socket_last_error());
return false;
}
return $new_sock;
}/*}}}*/
public function connect($ip, $port, $timeout, &$sock)
{/*{{{*/
$sock=socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_nonblock($sock);
if(@socket_connect($sock, $ip, $port) == true)
{
socket_set_block($sock);
return true;
}
$error=socket_last_error();
if($error != SOCKET_EINPROGRESS && $error != SOCKET_EWOULDBLOCK)
{
errlog::add("%s|%s: connect fail:".$error,
basename(__FILE__), __METHOD__);
socket_close($sock); $sock=null;
return false;
}
$read=$write=array($sock);
$num=socket_select($read, $write, $exp=null, $timeout, 0);
if($num === false || $num == 0)
{
errlog::add("%s|%s): connect select fail:".
socket_last_error(),
basename(__FILE__), __METHOD__);
socket_close($sock); $sock=null;
return false;
}
if(!in_array($sock, $read) && !in_array($sock, $write))
{
errlog::add("%s|%s: connect select invalid",
basename(__FILE__), __METHOD__);
socket_close($sock); $sock=null;
return false;
}
if(socket_getpeername($sock, $ip, $port) == false)
{
errlog::add("%s|%s: connect getpeername fail:".
socket_last_error(),
basename(__FILE__), __METHOD__);
socket_close($sock); $sock=null;
return false;
}
socket_set_block($sock);
return true;
}/*}}}*/
public function send($sock, $msg, $timeout)
{/*{{{*/
if(self::wait(self::$SEND, $sock, $timeout) == false)
{
errlog::add("%s|%s: send timeout",
basename(__FILE__), __METHOD__);
return false;
}
$buf=self::wrap($msg);
$left_size=strlen($buf);
$offset=0;
while($left_size > 0)
{
$sendbuf=substr($buf, $offset, $left_size);
$res=socket_send($sock, $sendbuf, strlen($sendbuf), 0);
if($res === false || $res == 0)
{
errlog::add("%s|%s: send fail, error:%d %s",
basename(__FILE__), __METHOD__,
socket_last_error(),
socket_strerror(socket_last_error()));
return false;
}
$left_size-=$res;
$offset+=$res;
if($left_size > 0)
{
if(self::wait(self::$SEND, $sock, $timeout) == false)
{
errlog::add("%s|%s: send timeout",
basename(__FILE__), __METHOD__);
return false;
}
}
}
return true;
}/*}}}*/
public function recv($sock, &$msg_out, $timeout)
{/*{{{*/
if(self::wait(self::$RECV, $sock, $timeout) == false)
{
errlog::add("%s|%s: recv timeout",
basename(__FILE__), __METHOD__);
return false;
}
$res=socket_recv($sock, $buf, self::MSG_SIZE_SIZE, 0);
if($res === false || $res == 0)
{
errlog::add("%s|%s: recv fail, error:%d %s",
basename(__FILE__), __METHOD__,
socket_last_error(),
socket_strerror(socket_last_error()));
return false;
}
$msg_out_size=intval($buf, 16);
$left_size=$msg_out_size;
while($left_size > 0)
{
$res=socket_recv($sock, $buf, $left_size, 0);
if($res === false || $res == 0)
{
errlog::add("%s|%s: recv fail, error:%d %s",
basename(__FILE__), __METHOD__,
socket_last_error(),
socket_strerror(socket_last_error()));
$msg_out=null;
return false;
}
$left_size-=$res;
$msg_out.=$buf;
if($left_size > 0)
{
if(self::wait(self::$RECV, $sock, $timeout) == false)
{
errlog::add("%s|%s: recv timeout",
basename(__FILE__), __METHOD__);
$msg_out=null;
return false;
}
}
}
return true;
}/*}}}*/
}
?>