前面的工作都准备好后,就可以开始入手swoole了。
现在就简单的对以下几个模块进行简单的上手入门,当然官方文档也有对应的使用方法,这里也只是简单的介绍上手。
HTML5的websocket文档:https://www.runoob.com/html/html5-websocket.html
目录:
Swoole的快速起步
1、tcp服务的学习和使用
2、udp服务的学习和使用
3、tcp、udp的介绍和它们的区别对比
4、tcp和udp客户端的使用
5、Http服务的学习和使用
6、websocket服务的使用
正文: tcp服务和udp服务的学习和使用
一、swoole支持的服务
swoole创建一个异步服务器程序,可以支持TCP、UDP、UnixSocket 3种协议,支持IPv4和IPv6,支持SSL/TLS单向双向证书的隧道加密。使用者无需关注底层实现细节,仅需要设置网络事件的回调函数即可。
二、swoole运行的流程图(来自官方文档)
swoole运行的流程图三、进程/线程结构图(来自官方文档)
进程/线程结构图 内部结构图四、通过第二点的swoole流程图,实现一个简单tcp服务的过程为:
(1)创建一个异步Server对象,具体可以参考server的函数文档(server的相关函数)
$serv = new Server(string $host, int $port = 0, int $mode = SWOOLE_PROCESS, int $sock_type = SWOOLE_SOCK_TCP);
(2)通过set函数,设置swoole配置
function Server->set(array $setting);
一些set方法的说明:
$serv->set(
array(
'reactor_num' => 2, // 通过此参数来调节Reactor线程的数量,以充分利用多核
'worker_num' => 4, // 设置启动的Worker进程数量。Swoole采用固定Worker进程的模式
'backlog' => 128, // 此参数将决定最多同时有多少个待accept的连接,swoole本身accept效率是很高的,基本上不会出现大量排队情况。
'max_request' => 50, // 此参数表示worker进程在处理完n次请求后结束运行。manager会重新创建一个worker进程。此选项用来防止worker进程内存溢出。
'dispatch_mode' => 1, //1平均分配,2按FD取模固定分配,3抢占式分配,默认为取模(dispatch=2)
)
);
(3)注册Server的事件回调函数on。
由于swoole是一个异步框架,里面的很多方法都是通过on函数绑定,通过回调进行后续操作。
bool Server->on(string $event, mixed $callback);
操作的大概流程为:
$serv->on('Connect', 'my_onConnect'); // 监听连接进入事件 ,tcp需要连接,udp不需要连接操作
$serv->on('Receive', 'my_onReceive'); // 监听数据接收事件
$serv->on('Close', 'my_onClose'); // 监听连接关闭事件
(4)启动服务
$serv->start();
五、简单示例
以上方法的简单实现示例(摘自官方文档):
<?php
//创建Server对象,监听 127.0.0.1:9501端口
$serv = new Swoole\Server("127.0.0.1", 9501);
//监听连接进入事件
$serv->on('Connect', function ($serv, $fd) { echo "Client: Connect.\n"; });
//监听数据接收事件
$serv->on('Receive', function ($serv, $fd, $from_id, $data) {
$serv->send($fd, "Server: ".$data);
});
//监听连接关闭事件
$serv->on('Close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//启动服务器
$serv->start();
?>
六、udp服务的简单示例
tcp和udp服务虽然都是使用swoole_server服务,但是区别在于创建一个异步服务时,指定模式为UDP: SWOOLE_SOCK_UDP。默认的模式是SWOOLE_SOCK_TCP。
需要注意的是:UDP服务器与TCP服务器不同,UDP没有连接的概念。启动Server后,客户端无需Connect,直接可以向Server监听的9502端口发送数据包。对应的事件为onPacket。
//创建Server对象,监听 127.0.0.1:9502端口,类型为SWOOLE_SOCK_UDP
$serv = new swoole_server("127.0.0.1", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
//监听数据接收事件
$serv->on('Packet', function ($serv, $data, $clientInfo) {
$serv->sendto($clientInfo['address'], $clientInfo['port'], "Server ".$data);
var_dump($clientInfo);
});
//启动服务器
$serv->start();
七、tcp协议和udp协议的区别对比
1、主要区别:
(1)TCP面向连接(如打电话要先拨号建立连接);UDP是无连接的,即发送数据之前不需要建立连接;
(2)TCP提供可靠的服务。也就是说,通过TCP连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP尽最大努力交付,即不保证可靠交付;
TCP通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
(3)UDP具有较好的实时性,工作效率比TCP高,适用于对高速传输和实时性有较高的通信或广播通信。
(4)每一条TCP连接只能是点到点的;UDP支持一对一,一对多,多对一和多对多的交互通信
(5)TCP对系统资源要求较多,UDP对系统资源要求较少。
2、为什么UDP有时比TCP更有优势?
UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。
采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。
3、为什么TCP不适用于实时传输?
TCP影响实时性不是因为握手消耗时间。握手一开始建立完就没事了
一般来说,单位时间内传输的数据流量比较平滑。 TCP依赖滑动窗口进行流量控制,滑动窗口大小是自适应的,影响滑动窗口主要有两个因素,一是网络延时,二是传输速率,滑动窗口的大小与延时成正比,与传输速率也成正比。在给定的网络环境下,延时可以认为是固定的,因此滑动窗口仅与传输速率有关,当传输实时数据时,因为数据流通量比较固定,所以这时TCP上的滑动窗口会处于一个不大不小的固定值,这个值大小恰好保证当前生产的数据实时传输到对方,当出现网络丢包时,按TCP协议(快速恢复),滑动窗口将减少到原来的一半,因此速率立刻减半,此时发送速率将小于数据生产速率,一些数据将滞留在发送端,然后滑动窗口将不断增大,直到积累的数据全部发送完毕。上述过程即为典型的TCP流量抖动过程,对于实时传输影响很大,可能形成较大的突发时延,从用户感观角度来说,就是有时比较流畅,但有时卡(“抖一下”,并且比较严重),因此实时传输通常不使用TCP。
4、udp和tcp可以应用的场景:
比如普通的会议视频图像,当然首选UDP,毕竟丢几包无所谓。
如果传输文件等,不能丢包,用TCP协议。
5、扩展:TCP协议的三次握手和四次挥手
(1)三次握手
为了准确无误的将数据发送到指定IP处,TCP协议采用了三次握手的策略,如下步骤所示:
①客户端采用TCP协议将带有SYN标志的数据包发送给服务器,等待服务器的确认。
②服务器端在收到SYN的数据包后,必须确认SYN,即自己发送的ACK标志,同时,自己也将会向客户端发送一个SYN标志。
③客户端在接收到服务器短的SYN+ACK包后,自己会向服务器发送ACK包,完成三次握手。那么客户端和服务器正式建立了连接,开始传输数据。
三次握手的图如下所示:
三次握手示例(2)四次挥手
四次挥手是用来断开服务器和客户端之间的通信的,之所以要断开连接,是因为TCP/IP 协议是要占用端口号的,而计算机的端口却是有限的,不进行断开的话,势必会造成计算机资源的浪费。
①在整个通信的过程中,谁先发起请求,谁就是客户端。
当客户端的数据传输到尾部时,客户端向服务器发送带有FIN标志的数据包,使其明白自己准备断开通信了。
②因为TCP的通信是使用全双工通信的WebSocket,所以在断开连接的时候也应该是双向的;当服务器收到带有FIN标志的数据包时,其必不会直接发送FIN标志断开通信的请求,而是先发送一个带有ACK标志的应答信息,使客户端明白服务器还有数据要进行发送。
③当 服务器的数据发送完成后,向客户端发送带有FIN标志的数据包,通知客户端断开连接。
④这一次挥手是我觉得四次挥手中设计的最巧妙的一次。
当客户端收到FIN后,担心网络上某些不可控制的因素导致服务器不知道他要断开连接,会发送ACK进行确认,同时把自己设置成TIME_WAIT状态并启动定时器,**在TCP的定时器到达后客户端并没有接收到请求,会重新发送;当服务器收到请求后就断开连接;当客户端等待2MLS(两倍报文最大生存时间)后,没有收到请求重传的请求后,客户端这边就断开连接,**整个TCP通信就结束了。
四次挥手的图如下所示:
四次挥手
网友评论