You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
2.9 KiB
139 lines
2.9 KiB
7 months ago
|
<?php
|
||
|
// namespace TestSuite;
|
||
|
|
||
|
require_once(dirname(__FILE__) . '/Error/SocketError.php');
|
||
|
// use \TestSuite\Exceptions\SocketError;
|
||
|
|
||
|
/**
|
||
|
* Socket连接类
|
||
|
*/
|
||
|
class Connection
|
||
|
{
|
||
|
const READ_SIZE = 1024;
|
||
|
|
||
|
protected $socket = null;
|
||
|
protected $options;
|
||
|
|
||
|
/**
|
||
|
* 创建一个新的socket连接.
|
||
|
* Options may be:
|
||
|
* - host (default: 127.0.0.1)
|
||
|
* - port (default: 3000)
|
||
|
*
|
||
|
* @param socket配置信息
|
||
|
*/
|
||
|
public function __construct($options)
|
||
|
{
|
||
|
$defaults = [
|
||
|
'host' => '127.0.0.1',
|
||
|
'port' => '3000'
|
||
|
];
|
||
|
|
||
|
$this->options = $options + $defaults;
|
||
|
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 建立socket连接
|
||
|
*
|
||
|
* @return bool
|
||
|
* @throws Exceptions\SocketError
|
||
|
*/
|
||
|
public function connect()
|
||
|
{
|
||
|
if (@socket_connect($this->socket, $this->options['host'], $this->options['port'])) {
|
||
|
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, [
|
||
|
'sec' => 50,
|
||
|
'usec' => 0
|
||
|
]);
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
throw new SocketError('Socket连接错误: ' . socket_last_error($this->socket));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 关闭socket
|
||
|
*
|
||
|
* @return void
|
||
|
*/
|
||
|
public function disconnect()
|
||
|
{
|
||
|
socket_shutdown($this->socket, 2);
|
||
|
socket_close($this->socket);
|
||
|
$this->socket = null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* 发送socket数据,并读取返回信息.
|
||
|
*
|
||
|
* @param string $data Hexed data string
|
||
|
*
|
||
|
* @throws TypeError
|
||
|
* @return string Answer returned from socket
|
||
|
*/
|
||
|
public function write($data)
|
||
|
{
|
||
|
// if (!ctype_xdigit($data)) {
|
||
|
// throw new TypeError('$data必须是16进制字符串');
|
||
|
// }
|
||
|
|
||
|
if ($this->socket === null) {
|
||
|
$this->connect();
|
||
|
}
|
||
|
|
||
|
// $binaryData = '';
|
||
|
|
||
|
// if ( !function_exists( 'hex2bin' ) ) {
|
||
|
|
||
|
// print_r('expression1');
|
||
|
// $len = strlen( $data );
|
||
|
// for ( $i = 0; $i < $len; $i += 2 ) {
|
||
|
// $binaryData .= pack( "H2", substr( $data, $i, 2 ) );
|
||
|
// }
|
||
|
// }else{
|
||
|
// print_r('expression2');
|
||
|
$binaryData = hex2bin($data);
|
||
|
// }
|
||
|
// $binaryData = $data;
|
||
|
// print_r("<pre>发送报文 => $data</pre>");
|
||
|
//发送数据
|
||
|
socket_write($this->socket, $binaryData);
|
||
|
|
||
|
// print_r('<pre>应答数据 => ');
|
||
|
//读取应答数据
|
||
|
$s = $this->socket;
|
||
|
$buffer = socket_read($s, self::READ_SIZE);
|
||
|
|
||
|
if (!$buffer) {
|
||
|
throw new SocketError('应答数据为空!');
|
||
|
}
|
||
|
|
||
|
$sockets = [$s];
|
||
|
while(socket_select($sockets, $w, $e, 0)) {
|
||
|
$buffer .= socket_read($s, self::READ_SIZE);
|
||
|
$sockets = [$s];
|
||
|
}
|
||
|
|
||
|
$buffer = bin2hex($buffer);
|
||
|
// print_r('$buffer');
|
||
|
|
||
|
// print_r('<pre>应答数据 => ');
|
||
|
// $buffer = '';
|
||
|
// if (false !== ($bytes = socket_recv($socket, $buffer, 2048, MSG_WAITALL))) {
|
||
|
// print_r ("共读取$bytes字节数据:");
|
||
|
// if (!$buffer) {
|
||
|
// throw new SocketError('应答数据为空!');
|
||
|
// }
|
||
|
// } else {
|
||
|
// throw new SocketError ("应答数据读取失败,原因: " . socket_strerror(socket_last_error($socket)));
|
||
|
// }
|
||
|
|
||
|
// print_r('</pre>');
|
||
|
socket_close($this->socket);
|
||
|
|
||
|
return $buffer;
|
||
|
}
|
||
|
}
|