创建TCP服务器

建议先阅读官方文档-创建TCP服务器章节.

  • 一、 Swoole-server介绍

  • 二、 创建一个Tcp server

  • 三、 swoole驱动模式及相应事件

  • 四、server跟client交互

  • 五、同步client跟异步client

  • 六、tcp的特点及粘包处理

一、 Swoole-server介绍

server,顾名思义,就是服务端。平时接触比较多的无非就是nginx和apache。作为webServer,二者都是通过监听某端口对外提供服务,swoole的server也不例外同样需要绑定端口,同时能够提供给客户端相关的服务。

创建server的步骤:

  • 1、实例化Server对象

  • 2、设置运行时参数

  • 3、注册事件回调函数

  • 4、启动服务器

示例:

<?php

//创建Server对象,监听 0.0.0.0:9501端口
$serv = new swoole_server("0.0.0.0", 9501,SWOOLE_PROCESS,SWOOLE_SOCK_TCP);

//配置
$serv->set([
    'worker_num' => 2, //设置进程
]);

//监听连接进入事件,有客户端连接进来的时候会触发
$serv->on('connect', function ($serv, $fd) {
     echo "有新的客户端连接,连接标识为$fd" . PHP_EOL;
});

//监听数据接收事件,server接收到客户端的数据后,worker进程内触发该回调
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
       var_dump($data);
       $serv->send($fd, "服务器给你发送消息了: ".$data);
});

//监听连接关闭事件,客服端关闭,或者服务器主动关闭
$serv->on('close', function ($serv, $fd) {
    echo "编号为{$fd}的客户端已经关闭.".PHP_EOL;
});

//启动服务器
$serv->start();

代码解析:

1、实例化Server对象

server的创建,只需要绑定要监听的ip和端口,如果ip指定为127.0.0.1,则表示客户端只能位于本机才能连接,其他计算机无法连接,如果需要所有的客户端都能连接则可以设置0.0.0.0.

//创建Server对象,监听 0.0.0.0:9501端口
$serv = new swoole_server("0.0.0.0", 9501,SWOOLE_PROCESS,SWOOLE_SOCK_TCP);

端口这里指定为9501,可以通过netstat查看下该端口是否被占用。如果该端口被占用,可更改为其他端口,如9502,9503等。

2、设置运行时参数

在启动service之前,同样也可以进行一些参数来配置一下server,比如调几个人来提供服务(几个进程),以及是否是后台执行(守护进程)等等一些其它的配置。

首要说明一下worker进程数的配置,因为swoole是多进程的异步服务器所以需要设置工作进程数,提升服务器性能。

$serv->set([
    'worker_num' => 2, //设置进程
]);

配置项worker_num等于某个正整数。这个正整数设置多少合适,即我要开多少个worker进程处理们的业务逻辑才好呢我?官方建议设置为CPU核数的1-4倍。因为开的进程越多,内存的占用也就更多,进程间切换也就需要耗费更多的资源。这里设置开启两个worker进程。默认该参数的值等于你机器的CPU核数

3、注册事件回调函数

swoole_server是事件驱动的。使用的过程中不需要关注底层是怎么实现的,底层是C写的,php只是做了个传递的作用,所以只需要对底层相应的动作注册相应的回调,在回调函数中处理业务逻辑即可。

什么意思?举个例子:

你启动了一个server,当客户端连接的时候(触发事件),你不需要关心它是怎么连接的,你就单纯的注册一个connect函数,做一些连接后的业务处理即可(执行业务)。类似于js的事件监听,比如触发了click事件,就会执行相应的闭包。

//监听连接进入事件,有客户端连接进来的时候会触发
$serv->on('connect', function ($serv, $fd) {
     echo "有新的客户端连接,连接标识为$fd" . PHP_EOL;
});

参数$serv是一开始创建的swoole_server对象,参数$fd是唯一标识,用于区分不同的客户端,同时该参数是1-1600万之间可以复用的整数。简单解释下复用:假设现在客户端1、2、3处于连接中,客户端4要连接的话$fd就是4,但是不巧的是客户端3连接不稳定,断掉了,客户端4连接到server的话,$fd就是3。

1600W个连接够用吗?单机业务百万连接,已经是很厉害了。

监听客户端数据发送,触发回调:

//监听数据接收事件,server接收到客户端的数据后,worker进程内触发该回调
$serv->on('receive', function ($serv, $fd, $from_id, $data) {
       $serv->send($fd, "服务器给你发送消息了: ".$data);
});

worker进程内触发的。第三个参数$fromId指的是哪一个reactor线程。第四个参数,这个参数就是服务端接受到的数据,注意是字符串或者二进制内容,注意在Receive回调内,调用了$serv的send方法,可以使用send方法,向client发起通知。

监听客户端关闭,触发回调:

//监听连接关闭事件,客服端关闭,或者服务器主动关闭
$serv->on('close', function ($serv, $fd) {
    echo "编号为{$fd}的客户端已经关闭.".PHP_EOL;
});

当客户端关闭,或者服务端主动关闭连接的时候会触发。

4、启动服务器

到此,基本上已经搭建到了一个高性能的server。当然,非常简单,下面只需要调用start方法启动server即可。

//启动服务器
$serv->start();

由于swoole_server只能运行在CLI模式下,所以不要试图通过浏览器进行访问:

$ php server.php

平时执行完一个指令,执行完就结束了,但是现在的情况正好相反,当前程序一直处于执行中的状态,并没有退出终端。同时因为swoole的server是常驻内存运行的,所以如果修改了代码,需要ctrl+c中断,重新运行程序使代码生效。

查看运行端口:

$ netstat -ntpl|grep 9501

服务器创建完成后需要创建一个client客户端和server服务端进行交互,请查看创建TCP客户端章节.

Last updated