闲暇时光 🌑
闲暇时光
我の闲暇时光 time flies
静谧时光,执笔抒心,岁月痕迹甚好。
109
21
58



Swoole中websocket Server的使用?

2021-09-24 14:02:18 - 2025-07-05 00:53:03
無慕 - 1.70K - 20.52分钟 - 1.63K

首先需要在系统中安装swoole服务!

PHP的ws_server.php文件中的代码:

//创建WebSocket Server对象,监听0.0.0.0:9502端口
$ws = new Swoole\WebSocket\Server('0.0.0.0', 9502);

//监听WebSocket连接打开事件
$ws->on('Open', function ($ws, $request) {
    $ws->push($request->fd, "hello, welcome\n");
});

//监听WebSocket消息事件
$ws->on('Message', function ($ws, $frame) {
    echo "Message: {$frame->data}\n";
    $ws->push($frame->fd, "server: {$frame->data}");
});

//监听WebSocket连接关闭事件
$ws->on('Close', function ($ws, $fd) {
    echo "client-{$fd} is closed\n";
});

$ws->start();
  • 客户端向服务器端发送信息时,服务器端触发 onMessage 事件回调

  • 服务器端可以调用 $server->push() 向某个客户端(使用 $fd 标识符)发送消息

在Linux中运行程序

php ws_server.php

可以使用 Chrome 浏览器进行测试,JS 代码为:

var wsServer = 'ws://127.0.0.1:9502';
var websocket = new WebSocket(wsServer);
websocket.onopen = function (evt) {
    console.log("Connected to WebSocket server.");
};

websocket.onclose = function (evt) {
    console.log("Disconnected");
};

websocket.onmessage = function (evt) {
    console.log('Retrieved data from server: ' + evt.data);
};

websocket.onerror = function (evt, e) {
    console.log('Error occured: ' + evt.data);
};

其他相关说明请查看:Swoole官网

编程 - 后端
插件 PHP

Linux系统下指定PHP命令使用的版本

2021-09-24 13:56:20 - 2025-07-05 00:53:03
無慕 - 209 - 10秒 - 1.86K

1、首先查看当前php命令运行的是哪个版本

ls /usr/bin/php -al

2、查看当前php运行目录

find / -name php

3、删除当前运行的目录

rm -rf /usr/bin/php

4.用ln -s 命令重新建立连接

ln -s /www/server/php/70/bin/php /usr/bin/php

编程 - 服务器
笔记 PHP Linux

MySQL中IFNULL的用法

2021-09-16 09:16:33 - 2025-07-05 00:53:03
無慕 - 1.27K - 3秒 - 1.68K

前置:本人测试使用的系统为windows,MySQL版本为5.7+,以下结果可能会受到影响,这里提前说明下。

表结构:

CREATE TABLE `ifnull_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `money1` decimal(10,2) DEFAULT NULL,
  `money2` decimal(10,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

表数据:

idmoney1money2
110.00(Null)
2(Null)-100.00
3150.0010.00

假设我要查询money1大于money2的,并且要把差值计算出来。SQL如下:

SELECT ( money1 - money2 ) AS money,money1,money2 FROM ifnull_test WHERE money1 > money2

但当表中数据存在null的情况下,不管是比较还是计算都会出问题,上面SQL的运行结果为:

moneymoney1money2
140.00150.0010.00

比我们预想的要差很多,按照我们的思维,表中的三条数据都是应该出现在结果中,这就需要用到IFNULL这个SQL函数了:

-- IFNULL() 函数用于判断第一个表达式是否为 NULL,如果为 NULL 则返回第二个参数的值,如果不为 NULL 则返回第一个参数的值。
IFNULL(expression, alt_value)

这时我们就可以加上这个函数完善上面的查询语句:

SELECT ( IFNULL(money1,0) - IFNULL(money2,0) ) AS money,money1,money2 FROM ifnull_test WHERE IFNULL(money1,0) > IFNULL(money2,0)

查询结果:

moneymoney1money2
10.0010.00(Null)
100.00(Null)-100.00
140.00150.0010.00

end!

编程 - 数据库
MySQL

MYSQL5.7版本sql_mode=only_full_group_by问题

2021-09-15 11:02:35 - 2025-07-05 00:53:03
無慕 - 1.13K - 0秒 - 1.50K

产生原因

前置:本人测试使用的系统为windows,MySQL版本为5.7+,以下结果可能会受到影响,这里提前说明下。

下载安装的是最新版的mysql5.7.x版本,默认是开启了 only_full_group_by 模式的,但开启这个模式后,原先的 group by 语句就报错,然后又把它移除了。

一旦开启 only_full_group_by ,感觉,group by 将变成和 distinct 一样,只能获取受到其影响的字段信息,无法和其他未受其影响的字段共存,这样,group by 的功能将变得十分狭窄了

only_full_group_by 模式开启比较好。

因为在 mysql 中有一个函数: any_value(field) 允许,非分组字段的出现(和关闭 only_full_group_by 模式有相同效果)。

解决办法

所以解决办法大致有两种:

第一种:

1、查看sql_mode

select @@global.sql_mode;

查询出来的值一般为:

ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

2、去掉ONLY_FULL_GROUP_BY,重新设置值。

set @@global.sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

3、上面是改变了全局sql_mode,对于新建的数据库有效。对于已存在的数据库,则需要在对应的数据下执行:

set sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';

第二种:

在sql查询语句中不需要group by的字段上使用any_value()函数。

这种对于已经开发了不少功能的项目不太合适,毕竟要把原来的sql都给修改一遍

编程 - 数据库
MySQL

MySQL中CAST的用法

2021-09-15 10:37:02 - 2025-07-05 00:53:03
無慕 - 349 - 8.28分钟 - 1.61K

CAST(expression AS TYPE) 函数可以将任何类型的值转换为具有指定类型的值,利用该函数可以直接在数据库层处理部分因数据类型引起的问题。

以下为该函数支持的数据类型:

支持的 TYPE

描述

BINARY

二进制型

CHAR

字符型

DATE

日期,格式为 ‘YYYY-MM-DD’

DATETIME

日期加具体的时间,格式为 ‘YYYY-MM-DD HH:MM:SS’

TIME

时间,格式为 ‘HH:MM:SS’

DECIMAL

float 型

SIGNED

int 型

UNSIGNED

无符号int

示例:

固定字符串转为SIGNED int 型

SELECT CAST("12321" AS SIGNED  ) AS result 
运行结果:12321

编程 - 数据库
MySQL

PHP异步(多进程)运行

2021-09-08 15:16:14 - 2025-07-05 00:53:03
無慕 - 1.26K - 4.65分钟 - 1.61K

前提:此命令在windows平台上不可用,且最好是在cli(命令行)下运行(ps:宝塔默认禁用pcntl_fork()函数)。

需要用到pcntl_fork()函数,此函数创建一个子进程,父进程和子进程都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程号,而子进程得到的是0。

const NEWLINE = "\n\n";
if (strtolower(php_sapi_name()) != 'cli') {
    die("请在cli模式下运行");
}
echo "当前进程(执行fork前):" . getmypid() . NEWLINE;
//fork出子进程
$pid = pcntl_fork(); 
//fork后父进程会走自己的逻辑,子进程从处开始走自己的逻辑,堆栈信息会完全复制给子进程内存空间,父子进程相互独立
if ($pid == -1) { // 创建错误,返回-1

    die('进程fork失败');
} else if ($pid) { // $pid > 0, 如果fork成功,在子进程中pid为0,而父进程中pid则大于0。

    // 父进程逻辑
    $time = microtime(true);
    $thispid=getmypid();
    echo "{$thispid}-{$pid}-我是父进程:{$time}".NEWLINE;

} else { // $pid = 0

    // 子进程逻辑
    $time = microtime(true);
    $thispid=getmypid();
    echo "{$thispid}-{$pid}-我是子进程-{$pid}:{$time}".NEWLINE;
}

补充:getmypid()获取当前进程id。

编程 - 后端
PHP 笔记

PHP的四种运行模式

2021-09-08 14:23:12 - 2025-07-05 00:53:03
無慕 - 733 - 15秒 - 1.57K

一、mod_php

一个单独的控制进程(父进程)负责产生子进程,这些子进程用于监听请求并作出应答。

Apache总是试图保持一些备用的 (spare)或是空闲的子进程用于迎接即将到来的请求。

这样客户端就无需在得到服务前等候子进程的产生。

最明显的例子就是在CGI模式下,如果修改了php.ini的配置文件,不用重启web服务便可生效(每次都会加载php.ini的配置,这也是导致性能能地下的一个原因)。而模块模式下需要重启web服务。

以mod_php模式运行PHP,意味着PHP是作为Apache的一个模块来启动的,因此只有在Apache启动的时候会读取php.ini配置文件并加载扩展模块,在Apache运行期间是不会再去读取和加载扩展模块的。

二、CGI(公共网关接口)

当一个服务web-service(nginx)分配过来请求的时候,通过匹配后缀是动态的php的请求。CGI就会去读取php.ini的基本配置信息,初始化环境,创建进程,返回数据,退出进程。每一次请求都是循环往复,所以有些繁琐,这是后面为什么会诞生fastcgi的原因。

三、FastCGI(cgi的改进版)

这种形式是CGI的加强版本,CGI是单进程,FastCGI多线程的运行方式,程序执行完成之后就会销毁,所以每次都需要加载配置和环境变量fork-and-execute(创建-执行)。

而FastCGI则不同,FastCGI 像是一个常驻 (long-live) 型的 CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去 fork 一次。

FastCGI进程管理器自身初始化,启动多个CGI解释器进程 (在任务管理器中可见多个php-cgi.exe)并等待来自Web Server的连接。

四、CLI

命令行运行。

编程 - 后端
PHP 笔记

isset()判断数组有坑,但可用array_key_exists()来填

2021-09-08 14:18:50 - 2025-07-05 00:53:03
無慕 - 680 - 30秒 - 1.63K

array_key_exists() 会检查键值的存在. 这个函数会返回TRUE,只要键值存在,即使值为NULL.

$data = array("one" => "1", "two" => "", "three" => null);
var_dump(array_key_exists("one", $data));// true
var_dump(array_key_exists("two", $data));// true
var_dump(array_key_exists("three", $data));// true

和arrry_key_exitst()不同,isset()会同时检查键和值,只有当健存在,对应的变量不为NUll的时候才会返回TURE。

$data = array("one" => "1", "two" => "", "three" => null);
var_dump(isset($data['one']));// true
var_dump(isset($data['two']));// true
var_dump(isset($data['three']));// false

编程 - 后端
实用 笔记 PHP

如何通过命令修改宝塔的默认8888端口?

2021-08-16 10:19:35 - 2025-07-05 00:53:03
無慕 - 620 - 3秒 - 1.71K

因为有时候公司服务器的端口不会全部开放,所以安装好后的宝塔可能无法用默认的8888端口访问,所以查询了一下解决办法。

修改面板端口,如要改成38888(centos 6 系统)

echo '38888' > /www/server/panel/data/port.pl && /etc/init.d/bt restart
iptables -I INPUT -p tcp -m state --state NEW -m tcp --dport 38888 -j ACCEPT
service iptables save

修改面板端口,如要改成38888(centos 7 系统)

echo '38888' > /www/server/panel/data/port.pl && /etc/init.d/bt restart
firewall-cmd --permanent --zone=public --add-port=38888/tcp
firewall-cmd --reload

亲测有效!

编程 - 服务器
宝塔面板

当一个服务器80端口被封,域名无法访问服务时怎么办?

2021-08-06 16:32:17 - 2025-07-05 00:53:03
無慕 - 2.43K - 6秒 - 1.90K

产生原因描述

现在我有一台服务器,这里叫服务器①,服务器①的80端口因为某些原因被封了,而原来指向这台服务器的域名全都失效了,只能通过服务器①的ip:端口号的方式进行访问,这样用户体验极差,所以找办法解决了一下,于是有了下面的方案。

处理方式

前提

需要两台服务器(服务器①和服务器②,服务器①是源码所在服务器),以及域名解析权限。

步骤

  • 首先解析一个ip:端口号的访问地址,并确保能正常访问。

  • 然后把想要恢复正常的网站解析到服务器②上,然后此服务器打开Nginx的配置,在配置的最后一行会有这么一句:

include /www/server/panel/vhost/nginx/*.conf;
  • 我们去打开这个目录,因为他是用*进行加载的配置,所以这里建议每个网站建立一个conf文件,文件名随意,但建议和域名同步,防止混乱后期也便于维护,要配置的内容是:

upstream shx {
server 服务器①的ip:端口号 weight=1;
}

server {
        listen 80;
        server_name 解析的域名地址;
        index index.html;

        location / {
            proxy_pass          http://shx/;
            proxy_set_header    X-Forwarded-For         $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto       $scheme;
            proxy_set_header    X-Forwarded-Port        $server_port;
            proxy_set_header    Host                    $host;
            proxy_set_header    X-Real-IP               $remote_addr;
        }
        location ~ ^/(WEB-INF)/ {
            deny all;
        }
}
  • 配置好后就可以通过域名正常访问,看上去是域名进行访问,但实际上访问的是ip:端口号。

注意

因为此目录下所有配置是一起加载的,所以每个upstream后面的名字都要不一样,下面proxy_pass中的也要相应替换。

补充

这个方法还有其它作用,例如某阿域名要求必须绑定自己公司的服务器,如果你绑定其他公司的服务器,会导致网站无法正常访问,也可以用这种方法,先解析到某阿自己的服务器,再指向到自己的服务器。

编程 - 服务器
服务器 Nginx 教程
1…23456…11
鲁ICP备2023049263号-1
© 2020 – 至今 闲暇时光
由 PHP MySQL 开发而成 | 主题 - Yun
upyun