Swoole 中使用 TCP 异步服务器、TCP 协程服务器、TCP 同步客户端、TCP 协程客户端
TCP 异步风格服务器
异步风格服务器通过监听事件的方式来编写程序。当对应的事件发生时底层会主动回调指定的函数。
由于默认开启协程化,在回调函数内部会自动创建协程,遇到 IO 会产生协程调度,异步风格服务器无法保证调度顺序,所以在遇到并发时无法保证事件执行顺序。
# server.php
// 创建 TCP 服务器对象,监听 0.0.0.0:9501端口
$serv = new Swoole\Server("0.0.0.0", 9501);
// 设置服务器运行参数
$serv->set(array(
'daemonize' => 1, // 作为守护进程运行,需同时设置log_file
'log_file' => '/www/logs/swoole.log', // 指定标准输出和错误日志写入的文件
));
// 监听连接进入事件
// $fd 为客户端连接的唯一标识符
$serv->on('Connect', function ($serv, $fd) {
echo "Client: Connect: {$fd} .\n";
});
// 监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
// 向指定的客户端连接发送数据
$serv->send($fd, "Server: " . $data);
});
// 监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
echo "Client: Close: {$fd} .\n";
});
// 监听服务器正常关闭事件
// 使用 kill -15 发送 SIGTREM 信号到主进程正常关闭时触发
// kill -9 或 Ctrl+C 不会触发该事件
$serv->on('Shutdown', function ($serv) {
echo "服务器正常关闭.\n";
});
// 启动服务器
$serv->start();
运行并测试 TCP 异步风格服务器
# 如果程序已经运行,先结束进程
kill -9 11590
# 在 cli 命令行环境运行服务端
php server.php
# 查看服务器监听的端口
netstat -an | grep 9501
# 使用Telnet测试连接服务端
telnet 127.0.0.1 9501
# 发送数据
hello
# 接收数据
Server: hello
TCP 协程风格服务器
协程风格服务器处理连接的过程是完全同步的,程序可以顺序处理 Connect、Receive、Close 事件,可以保证事件执行顺序。
由于 TCP 协程风格服务器不支持设置工作进程数,服务器每次只能处理一个连接请求,如果请求中包含耗时逻辑,会严重影响并发性能,所以需要借助进程池实现多核CPU的利用。
# server.php
// 在进程池中创建两个进程
$pool = new Swoole\Process\Pool(2);
$pool->set([
'enable_coroutine' => true, // 让每个 OnWorkerStart 回调都自动创建一个协程
'daemonize' => 1, // 作为守护进程运行,需同时设置log_file
'log_file' => '/www/logs/swoole.log', // 指定标准输出和错误日志写入的文件
]);
// 进程绑定工作进程启动事件
$pool->on('workerStart', function ($pool, $id) {
// 每个进程都监听9501端口,不使用ssl,开启端口重用
$server = new Swoole\Coroutine\Server('0.0.0.0', '9501', false, true);
// 接收 kill -15 信号关闭服务器
Swoole\Process::signal(SIGTERM, function () use ($server) {
echo "服务器正常关闭.\n";
$server->shutdown();
});
// 设置连接处理函数,接收到新的连接请求并自动创建一个协程并执行回调函数
// 回调函数会在协程空间中执行
$server->handle(function(Swoole\Coroutine\Server\Connection $conn) {
echo "Client: Connect.\n";
// 循环接收和返回数据
while (true) {
// 接收数据
$data = $conn->recv();
if (empty($data)) {
// 关闭连接
$conn->close();
break;
}
//发送数据
$conn->send("Server: " . $data);
\Co::sleep(1);
}
});
// 启动服务器
$server->start();
});
$pool->start();
由于TCP 协程风格服务器同一时间只能处理一个连接,为了充分利用CPU多核、处理多个连接,需要用到Swoole中的多进程模型+端口重用。
TCP 同步阻塞客户端
// 同步阻塞客户端可以用于 PHP-FPM 环境下
$client = new Swoole\Client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_SYNC);
if (!$client->connect('127.0.0.1', 9501, -1)) {
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world\n");
// 同步阻塞等待服务端返回内容
echo $client->recv();
$client->close();
TCP 协程客户端
// 设置要 Hook 的函数的范围
Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
// 协程客户端,底层自动使用协程调度实现异步IO,用于代替异步客户端
Co\run(function(){
$client = new Swoole\Coroutine\Client(SWOOLE_SOCK_TCP);
$client->set(array(
'timeout' => 1.5, //总超时,包括连接、发送、接收所有超时
'connect_timeout' => 1.0, //连接超时,会覆盖第一个总的 timeout
'write_timeout' => 2.0, //发送超时,会覆盖第一个总的 timeout
'read_timeout' => 0.5, //接收超时,会覆盖第一个总的 timeout
));
if (!$client->connect('127.0.0.1', 9501, 0.5)) {
exit("connect failed. Error: {$client->errCode}\n");
}
$client->send("hello world.\n");
echo $client->recv();
$client->close();
});
Swoole 中使用 TCP 异步服务器、TCP 协程服务器、TCP 同步客户端、TCP 协程客户端的更多相关文章
- Swoole 中使用 WebSocket 异步服务器、WebSocket 协程服务器
WebSocket 异步风格服务器 WebSocket\Server 继承自 Http\Server,所以 Http\Server 提供的所有 API 和配置项都可以使用. # ws_server.p ...
- Swoole 中使用 HTTP 异步服务器、HTTP 协程服务器
HTTP 异步风格服务器 # http_server.php $http = new Swoole\Http\Server("0.0.0.0", 9501); // 设置服务器运行 ...
- Swoole 中使用 UDP 异步服务器、UDP 同步客户端、UDP 协程客户端
UDP 异步风格服务器 # udp_server.php // 创建 UDP 服务器对象,监听0.0.0.0:9502端口,类型为SWOOLE_SOCK_UDP $serv = new Swoole\ ...
- 一种C# TCP异步编程中遇到的问题
最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,G ...
- Java TCP异步数据接收
之前一直采用.Net编写服务端程序,最近需要切换到Linux平台下,于是尝试采用Java编写数据服务器.TCP异步连接在C#中很容易实现,网上也有很多可供参考的代码.但Java异步TCP的参考资料较少 ...
- 基于C#的socket编程的TCP异步实现
一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...
- (转)基于C#的socket编程的TCP异步实现
一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...
- 客户端程序通过TCP通信传送"小文件"到服务器
客户端程序通过TCP通信传送"小文件"到服务器 [c#源码分享]客户端程序通过TCP通信传送"小文件"到服务器 源码 (不包含通信框架源码,通信框架源码请另行 ...
- [转]Linux服务器上11种网络连接状态 和 TCP三次握手/四次挥手详解
一.Linux服务器上11种网络连接状态: 图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手. 注:以下说明最好能结合”图:T ...
随机推荐
- ReactiveCocoa操作方法-秩序
doNext: 执行Next之前,会先执行这个Block doCompleted: 执行sendCompleted之前,会先执行这个Block - (void)doNext { [ ...
- 【编程思想】【设计模式】【其他模式】blackboard
Python版 https://github.com/faif/python-patterns/blob/master/other/blackboard.py #!/usr/bin/env pytho ...
- spring boot 启动卡半天
测试服务器到期,把环境切了,早上过来 ios 和 安卓 都说 测试环境连不上,ps -ef | grep app.jar 查看了一下进程,发现没有启动,于是 重新打包.部署,一顿骚操作后,监控启动日志 ...
- 【Linux】【Services】【SaaS】Docker+kubernetes(1. 基础概念与架构图)
1.简介 1.1. 背景:公司正在进行敏捷开发环境的搭建,以取代传统的架构,好处大大的,我就不赘述了.公司原来负责这个项目的同事要转组,我只好交给另外同事继续,但是为了防止同样的事情,我也需要深入了 ...
- SQL查询:并集、差集、交集
新建两个表进行测试: test_a ID name 1 曹操 2 郭嘉 3 孙权 4 周瑜 test_b ID name 1 刘备 2 关羽 3 张飞 4 孙权 5 周瑜 1.UNION形成并集 UN ...
- 特定场景下的PLC 远程控制和数据读取
最近有位博友提出了一种应用场景,根据工作中实际遇到的类似的产品应用场景,记录下自己的解决方案. 场景: 需要在云端控制和采集各个站点的PLC数据.各个站点是分散的,每个站点有公网访问能力,但是分散站点 ...
- 基于Kubernetes的hpa实现pod实例数量的自动伸缩
Pod 是在 Kubernetes 体系中,承载用户业务负载的一种资源.Pod 们运行的好坏,是用户们最为关心的事情.在业务流量高峰时,手动快速扩展 Pod 的实例数量,算是玩转 Kubernetes ...
- Abp Vnext 替换Redis的实现为csredis
Host项目安装csredis的nuget包和data protect包并 移除 Microsoft.Extensions.Caching.StackExchangeRedis Microsoft.A ...
- Redis监控参数
目录 一.客户端 二.服务端 一.客户端 127.0.0.1:6379> info stats #Redis自启动以来处理的客户端连接数总数 total_connections_received ...
- MVCC详解
参考: https://blog.csdn.net/SnailMann/article/details/94724197 https://blog.csdn.net/DILIGENT203/artic ...