page contents

PHP 下的 Socket 编程

以下内容希望帮助到大家!

attachments-2020-04-a07ETcP15ea8e6b5050ed.jpg

Socket 并不是一个协议, 其本质是对 TCP/IP 协议进行的封装, 并对外提供了一组接口, 允许用户可以自由的按相关协议组装数据, 与服务器进行交互。

一切基于 TCP/IP 的协议可以通过 Socket 进行实现。


PHP 通过 Socket 扩展也可以实现对 Socket 编程,使用 PHP 进行 Socket 通信的简单过程如下:

v2-417cd7a9a13cf786ba17c24d46492965_720w.jpg

PHP Socket 编程涉及的主要函数:

socket_create(): 初始化一个socket资源
socket_bind(): 将socket资源绑定到指定地址
socket_listen(): 监听socket的连接请求
socket_accept(): 接受来自客户端的连接, 返回一个新socket资源用于通讯. 如果接收到多个连接, 只会使用第一个连接. 没有连接时, 该函数保持堵塞状态, 直到有新的连接. 如果使用socket_set_blocking() or socket_set_nonblock()将socket设置为非堵塞状态, 没有连接时该函数返回FALSE
socket_read(): 从连接资源中读取指定字节数的数据, 读取成功时, 返回字符串. 失败时, 返回FALSE. 没有数据时, 返回空字符串
socket_write(): 向连接资源写入信息返回给客户端
socket_strerror(): 根据错误号获取错误消息
socket_last_error(): 返回上一次错误的错误号


示例一: 客户端和服务端的一对一通信, 由客户端推送数据到服务端

client.php

$host = '127.0.0.1';
$port = 65533;
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
exit('初始化socket资源错误: ' . socket_strerror(socket_last_error($sock)));
}
 
if(socket_connect($sock, $host, $port) === FALSE)
{
exit('连接socket失败: ' . socket_strerror(socket_last_error($sock)));
}
 
$msg = '客户端1消息';
if(socket_write($sock, $msg) === FALSE)
{
exit('发送数据失败: ' . socket_strerror(socket_last_error($sock)));
}
 
$data = '';
// 循环读取指定长度的服务器响应数据
while($response = socket_read($sock, 4))
{
$data .= $response;
}
echo $data . PHP_EOL;
 
socket_close($sock);

server.php

set_time_limit(0);
 
$ip = '127.0.0.1';
$port = '65533';
$count = 1;
// socket_create(): 初始化一个socket资源
// socket_strerror(): 根据错误号获取错误消息
// socket_last_error(): 返回上一次错误的错误号
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
echo '初始化socket失败: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_bind(): 将socket资源绑定到指定地址
if(!socket_bind($sock, $ip, $port))
{
echo '绑定端口失败: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_listen(): 监听socket的连接请求
if(!socket_listen($sock))
{
echo '监听端口: ' . socket_strerror(socket_last_error($sock));
die;
}
 
while(1)
{
// socket_accept(): 接受来自客户端的连接, 返回一个新socket资源用于通讯. 如果接收到多个连接, 只会使用第一个连接. 没有连接时, 该函数保持堵塞状态, 直到有新的连接. 如果使用socket_set_blocking() or socket_set_nonblock()将socket设置为非堵塞状态, 没有连接时该函数返回FALSE
;
if(($client = socket_accept($sock)) === FALSE)
{
echo '接收连接失败: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_read(): 从连接资源中读取指定字节数的数据, 读取成功时, 返回字符串. 失败时, 返回FALSE. 没有数据时, 返回空字符串
$content = socket_read($client, 1024);
if($content !== FALSE)
{
echo '消息' . $count . ': ' . $content . PHP_EOL;
$count++;
$response = '接收信息成功!';
// socket_write(): 向连接资源写入信息返回给客户端
socket_write($client, $response);
socket_close($client);
}else
{
exit('读取数据错误: ' . socket_strerror(socket_last_error($client)));
}
}
 
socket_close($sock);


首先在命令行下启动 server.php, 然后启动 client.php,

服务消息提示:

v2-888ffbdf870adb6d326d5f33e0bc5e97_720w.jpg


客户端接收的响应消息提示

v2-0a2a8f7005ef6f120f5875ecd01baa9f_720w.jpg

客户端接收到服务端的响应消息后将断开连接, 而服务端会一直挂起, 等待下一次的连接.


示例二: 客户端和服务端的一对一通信, 由服务端推送数据到客户端

client.php

// 服务端地址
$host = '127.0.0.1';
$port = 65533;
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
exit('初始化socket资源错误: ' . socket_strerror(socket_last_error($sock)));
}
 
if(socket_connect($sock, $host, $port) === FALSE)
{
exit('连接socket失败: ' . socket_strerror(socket_last_error($sock)));
}
 
$data = '';
// 循环读取指定长度的服务器响应数据
while($response = socket_read($sock, 4))
{
$data .= $response;
}
socket_write($sock, '接收消息成功');
echo $data . PHP_EOL;
 
socket_close($sock);

server.php

set_time_limit(0);
 
$ip = '127.0.0.1';
$port = '65533';
// socket_create(): 初始化一个socket资源
// socket_strerror(): 根据错误号获取错误消息
// socket_last_error(): 返回上一次错误的错误号
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
echo '初始化socket失败: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_bind(): 将socket资源绑定到指定地址
if(!socket_bind($sock, $ip, $port))
{
echo '绑定端口失败: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_listen(): 监听socket的连接请求
if(!socket_listen($sock))
{
echo '监听端口: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// 建立死循环,循环接收客户端的连接请求,持续向连接上的客户端推送消息
while(1)
{
// socket_accept(): 接受来自客户端的连接, 返回一个新socket资源用于通讯. 如果接收到多个连接, 只会使用第一个连接. 没有连接时, 该函数保持堵塞状态, 直到有新的连接. 如果使用socket_set_blocking() or socket_set_nonblock()将socket设置为非堵塞状态, 没有连接时该函数返回FALSE
;
if(($client = socket_accept($sock)) === FALSE)
{
echo '接收连接失败: ' . socket_strerror(socket_last_error($sock));
die;
}
$data = '服务端消息: ' . date('Y-m-d H:i:s', time());
socket_write($client, $data);
socket_close($client);
}
 
socket_close($sock);


首先通过命令行启动 server.php, 此时服务端将挂起, 持续监听指定端口.。

然后启动 client.php, 客户端发起连接, 连接成功后, 将接收到服务端推送的数据。


客户单响应提示:

v2-9f35c9f7c18ca96ef45c659ea003f33b_720w.jpg



attachments-2020-04-THfPdbut5ea8e6a343446.jpg

  • 发表于 2020-04-29 10:30
  • 阅读 ( 596 )
  • 分类:PHP开发

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1316 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章