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 协程风格服务器

协程风格服务器处理连接的过程是完全同步的,程序可以顺序处理 ConnectReceiveClose 事件,可以保证事件执行顺序。

由于 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 协程客户端的更多相关文章

  1. Swoole 中使用 WebSocket 异步服务器、WebSocket 协程服务器

    WebSocket 异步风格服务器 WebSocket\Server 继承自 Http\Server,所以 Http\Server 提供的所有 API 和配置项都可以使用. # ws_server.p ...

  2. Swoole 中使用 HTTP 异步服务器、HTTP 协程服务器

    HTTP 异步风格服务器 # http_server.php $http = new Swoole\Http\Server("0.0.0.0", 9501); // 设置服务器运行 ...

  3. Swoole 中使用 UDP 异步服务器、UDP 同步客户端、UDP 协程客户端

    UDP 异步风格服务器 # udp_server.php // 创建 UDP 服务器对象,监听0.0.0.0:9502端口,类型为SWOOLE_SOCK_UDP $serv = new Swoole\ ...

  4. 一种C# TCP异步编程中遇到的问题

    最近在维护公司的一个socket服务端工具,该工具主要是提供两个socket server服务,对两端连接的程序进行数据的透明转发. 程序运行期间,遇到一个问题,程序的一端是GPRS设备,众所周知,G ...

  5. Java TCP异步数据接收

    之前一直采用.Net编写服务端程序,最近需要切换到Linux平台下,于是尝试采用Java编写数据服务器.TCP异步连接在C#中很容易实现,网上也有很多可供参考的代码.但Java异步TCP的参考资料较少 ...

  6. 基于C#的socket编程的TCP异步实现

    一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...

  7. (转)基于C#的socket编程的TCP异步实现

    一.摘要 本篇博文阐述基于TCP通信协议的异步实现. 二.实验平台 Visual Studio 2010 三.异步通信实现原理及常用方法 3.1 建立连接 在同步模式中,在服务器上使用Accept方法 ...

  8. 客户端程序通过TCP通信传送"小文件"到服务器

    客户端程序通过TCP通信传送"小文件"到服务器 [c#源码分享]客户端程序通过TCP通信传送"小文件"到服务器 源码  (不包含通信框架源码,通信框架源码请另行 ...

  9. [转]Linux服务器上11种网络连接状态 和 TCP三次握手/四次挥手详解

    一.Linux服务器上11种网络连接状态: 图:TCP的状态机 通常情况下:一个正常的TCP连接,都会有三个阶段:1.TCP三次握手;2.数据传送;3.TCP四次挥手. 注:以下说明最好能结合”图:T ...

随机推荐

  1. Python初探——sklearn库中数据预处理函数fit_transform()和transform()的区别

    敲<Python机器学习及实践>上的code的时候,对于数据预处理中涉及到的fit_transform()函数和transform()函数之间的区别很模糊,查阅了很多资料,这里整理一下: ...

  2. 【Linux】【专项突破】Linux重定向与管道

    [专项突破]Linux重定向与管道 This article is written by Xrilang(Chinese Name:萌狼蓝天) If you want find me ,You can ...

  3. Linux目录终章,单用户模式修改密码、环境变量、第三方软件安装

    目录 今日内容概要 内容详细 解析映射文件 磁盘挂载文件 开机加载脚本 系统启动级别 使用单用户模式修改密码 变量加载文件 登录提示信息 第三方软件安装目录(编译安装目录) 系统日志目录 保存系统运行 ...

  4. 07- Vue3 UI Framework - Switch 组件

    为了更好的提升用户体验,我们这里再做一个很常用的开关组件 switch 返回阅读列表点击 这里 需求分析 开始之前我们先做一个简单的需求分析 switch 组件应分为选中/未被选中,两种状态 可以通过 ...

  5. CTF靶场

    CTF靶场测试报告 一.跨站脚本攻击(XSS) 实验原理:跨站脚本攻击( Cross Site Script),本来的缩写应为CSS,但是为了与层叠样式表(Cascading Style CSS)区分 ...

  6. 为什么众多软件厂商无法提供APS高级计划排程系统?工厂目前生产计划是怎么排产的?

    一.行业现状如想了解一下目前现状,去考察一下上了ERP的企业,会发现一个有趣的现象该企业无论ERP软件搞得如何如火如荼,似乎都与生产调度人员无关. 车间里或者生产线上的生产作业计划.生产过程的调度和管 ...

  7. CF1177A Digits Sequence (Easy Edition) 题解

    Content 一个序列由从 \(1\) 开始的数字不断在末端拼接,就像这样:\(12345678910111213141516...\).现在,给定一个数字 \(k\),请输出这个序列的第 \(k\ ...

  8. 『学了就忘』Linux系统定时任务 — 89、任务调度工具anacron

    目录 1.任务调度工具anacron介绍 2.新旧版本Linux中anacron工具的区别 3./etc/cron.{daily,weekly,monthly}目录说明 4.anacron命令 5./ ...

  9. Tornado 之 WebSocket

    7.3 WebSocket WebSocket是HTML5规范中新提出的客户端-服务器通讯协议,协议本身使用新的ws://URL格式. WebSocket 是独立的.创建在 TCP 上的协议,和 HT ...

  10. 在程序出现问题,当找不到错误时,第一时间用try ,catch包括起来

    在程序出现问题,当找不到错误时,第一时间用try ,catch包括起来,把错误找到.