PHP中使用socket进行通信

码农天地 -
PHP中使用socket进行通信

1. socket 概述
socket 也称作套接字,用于描述 IP 地址和端口,是一个通信链的句柄,可以用来实现不同计算机之间的通信。socket 是对 TCP / IP 协议的封装,它只是提供了一组针对 TCP 或者 UDP 进行编程的接口(API)。
socket 利用客户端 / 服务器端的模式巧妙地解决了进程之间建立通信连接的问题。

2. socket 的工作原理
服务器端先初始化 socket,然后与端口绑定(bind),对端口进行监听(listen),等待客户端连接,调用accept阻塞。
这时,如果有客户端初始化一个 socket,然后请求连接服务器(connect),如果连接成功,客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把响应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

3. socket通信演示
服务器端的代码:
(在 E:\xampp\htdocs\demo 下新建一个php文件socket_server.php)
<?php
// 设置脚本最大执行时间,单位为秒,0表示永不超时
set_time_limit(0);

$address = '127.0.0.1';
$port = 10005;   // 端口可以是1到65535之间的任何数字,前提是未被占用

// 创建并返回一个套接字(通讯节点),一个典型的网络连接由 2 个套接字构成,一个运行在服务器端,另一个运行在客户端
if( ($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
echo "socket_create() failed, reason: " . socket_strerror(socket_last_error()) . "\n";
}

// 绑定socket到具体的主机端口
if (socket_bind($sock, $address, $port) === false) {
echo "socket_bind() failed, reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

// 监听socket服务器上的请求连接,等待接入
if (socket_listen($sock, 5) === false) {
echo "socket_listen() failed, reason: " . socket_strerror(socket_last_error($sock)) . "\n";
}

do {
// 确认客户端的连接请求,成功后,返回一个新的子socket句柄(子线程),用于通信
if (($msgsock = socket_accept($sock)) === false) {
echo "socket_accept() failed, reason: ".socket_strerror(socket_last_error($sock)) . "\n";
break;
}

$msg = "Welcome to connect '$address'"."\n";
// 发送消息(数据)到客户端
if (false === socket_write($msgsock, $msg, strlen($msg))){
echo "socket_write() failed, reason: " . socket_strerror(socket_last_error($sock)) ."\n";
}

echo "Read client message \n";
// 读取客户端的数据
$receivedData = socket_read($msgsock, 8192);
echo "Received message: ".$receivedData."\n";;

// 将客户端发来的数据,进行处理,然后再发送数据给客户端
$responseData = '[time:'.date('Y-m-d H:i:s').']'.PHP_EOL.'[data:'.trim($receivedData).']';
if (false === socket_write($msgsock, $responseData, strlen($responseData))) {  
echo "socket_write() failed, reason: " . socket_strerror(socket_last_error($sock)) ."\n";
}

// 关闭连接成功的子socket
socket_close($msgsock);
} while(true);

// 关闭等待接入的socket
socket_close($sock);
?>
服务器端的代码,需要在 cmd 下或者 CLI模式下运行,打开命令行窗口,输入如下命令:
php E:\xampp\htdocs\demo\socket_server.php
就可以在服务器端运行socket服务。
注意:服务器端的命令行窗口不可关闭。

客户端的代码:
(在 E:\xampp\htdocs\demo 下新建一个php文件socket_client.php)
<?php
$address = '127.0.0.1';
$service_port = 10005;

// 创建并返回一个套接字(通讯节点)
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
echo "socket_create() failed, reason: ".socket_strerror(socket_last_error())."\n";
}

echo "Attempting to connect to '$address' on port '$service_port'...";
// 发起socket连接请求
$result = socket_connect($socket, $address, $service_port);
if($result === false) {
echo "socket_connect() failed, reason: ".socket_strerror(socket_last_error($socket))."\n";
} else {
echo "Connect success. \n";
}

$input = "This is a message from client"."\n";

// 向socket服务器发送消息
socket_write($socket, $input, strlen($input));
echo  "Client send success \n";

echo "Reading response:\n";
// 读取socket服务器发送的消息
while ($out = socket_read($socket, 8192)) {
echo $out;
}
echo PHP_EOL;
socket_close($socket); // 关闭socket连接
?>
客户端的代码,可以在浏览器中运行(如:http://demo.com/socket_client.php),也可以在命令行窗口运行,新打开一个cmd,输入如下命令:
php E:\xampp\htdocs\demo\socket_client.php
就可以看到客户端与服务器端进行通信的结果。

最后,推荐使用 Workerman 来实现 socket 通信。(详情可参考 Workerman官网)
Workerman 是一款纯 PHP 开发的开源高性能的 PHP Socket 服务器框架。被广泛的用于手机app、手游服务端、网络游戏服务器、聊天室服务器、硬件通讯服务器、智能家居、车联网、物联网等领域的开发。 支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。基于workerman,开发者可以更专注于业务逻辑开发,不必再为 PHP Socket 底层开发而烦恼。

Tags 标签

socket通信通信

扩展阅读

加个好友,技术交流

1628738909466805.jpg