赞
踩
一直不能下决心好好学习,仔细研究一下,决定用尽量降低难度曲线的方法,从易到难,一步一步的学习,所以整了个 demo 项目。
git 仓库和使用步骤
确保能看到swoole,在 php -m 命令中
php -m
git clone https://github.com/lang123789/swoole_demo.git
然后设置了标签,本文对应 v4.0
cd swoole_demo
git checkout v4.0
有提示错误之类,但代码已经切换到 v4.0 了。
另外,前面 3 版其实有一些 js 错误,一并修复了。
## 安装类库,生成 autoload.php 文件
composer install
## 启动 websocket 服务
php src/WebSocket/run.php
需求
6、需要能正常聊天。就是别人说话,其他每个在聊天室的人都能看到这个人说的话。
7、如果某人上线,他自己看到 欢迎您,某某某,其他人看到,某某某 上线了。
8、如果某人下线。其他人看到,某某某 下线了。
测试网址
127.0.0.1/index.php?id=1
127.0.0.1/index.php?id=2
主要代码
客户端主要代码
客户端代码主要在 index.php 中
function activate_chat_js() {
const me = 1;
const chatter = 0;
// 这是每个人自己发消息。子程序1。
function update_chatWindow(incoming_message, from) {
if (from === 1) {
var msg_html = my_message_html(incoming_message);
} else if (from === 0) {
var msg_html = chatter_message_html(incoming_message);
}
$(".chat-window").append(msg_html);
}
// 这是自己发消息。子程序2。
function my_message_html(incoming_message) {
var newMessage = '<div class="me-wrapper">' + '<div class="me-message container">' + incoming_message + '</div>' + '<div class="me-avatar">' + '我自己' +
'</div></div>';
return newMessage;
}
// click btn to send message
// 这也是每个人自己发消息。最开始点击。
$("#btn-send-message").click(function () {
var user_input_area = $("#user-input-value");
if (user_input_area.text().length == 0) {
} else {
var message=user_input_area.text();
update_chatWindow(user_input_area.text(), 1);
user_input_area.text("");
$('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
// v4.0修改,把消息给服务器。
window.websocket.send("my_message|{$user_id}|"+ message);
}
});
// ctrl+enter send message
// 这也是每个人自己发消息,用回车键。
$('#user-input-value').keydown(function (e) {
if ((event.keyCode == 10 || event.keyCode == 13)) {
$('#btn-send-message').trigger("click");
event.cancelBubble = true;
event.preventDefault();
}
});
}
// 这是显示在中间的系统消息。由服务器推送。
function system_chatWindow(incoming_message) {
var msg_html = '<div class="system-message">' + incoming_message + '</div>' ;
$(".chat-window").append(msg_html);
$('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
}
// v4.0 ,这是被onmessage函数调用的方法,
// 这是其他人发的消息,广播到每个机器。
function update_chatWindow2(incoming_message, from) {
var msg_html = '<div class="current-chatter-wrapper">' + '<div class="chatter-avatar">' + from + '</div>' + '<div class="chatter-message container">' + incoming_message + '</div>' + '</div>';
$(".chat-window").append(msg_html);
$('.chat-window').scrollTop($('.chat-window')[0].scrollHeight);
}
window.onload = function(){ activate_chat_js();
var wsServer = 'ws://{$JS_IP}:9501';
var websocket = new WebSocket(wsServer);
window.websocket = websocket;
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
websocket.send("my_id|{$user_id}");
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
var user = JSON.parse(evt.data);
if (user.type=='my_id'){
system_chatWindow(user.message);
}
// v4.0修改。其他人接受某人的消息广播。
if (user.type=='my_message'){
update_chatWindow2(user.message, user.from_user_name );
}
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
}
服务端主要代码
public function message(\swoole_websocket_server $server, \swoole_websocket_frame $frame)
{
$data = $frame->data;
echo "有消息:".$data."\n";
//这里用户发来的信息已经分类型了。my_id开头,说明是系统自动从客户端发送的信息,用于识别身份。
if (preg_match('#^my_id#', $data)) {
$user_id = explode("|", $data)[1];
$arr = $this->user_all;
$user_name = isset($arr[$user_id]) ? $arr[$user_id] : '';
if (!$user_name) {
//如果用户不存在,则我直接关闭连接。
echo "非法连接。用户id:" . $user_id;
$server->close($frame->fd);
return;
}
$user = [
'fd' => $frame->fd,
'user_name' => $user_name,
'user_id' => strval($user_id),
];
echo "有个人刚上线,数据:" . json_encode($user, JSON_UNESCAPED_UNICODE);
echo "\n";
// 放入内存表
$this->table->set($frame->fd, $user);
//给本人看 欢迎您。
$server->push($frame->fd, json_encode([
'type' => 'my_id',
'message' => '欢迎您,' . $user_name,
]));
// 通知其他人 某某 上线了。
foreach ($this->table as $row) {
if ($row['fd'] != $frame->fd) {
$server->push($row['fd'], json_encode([
'type' => 'my_id',
'message' => $user_name . ' 上线了',
]));
}
}
} elseif (preg_match('#^my_message#', $data)) {
$user_id = explode("|", $data)[1];
$message = explode("|", $data)[2];
$arr = $this->user_all;
$user_name = isset($arr[$user_id]) ? $arr[$user_id] : '';
if (!$user_name) {
//如果用户不存在,则w我直接关闭连接。
echo "非法连接。用户id:" . $user_id;
$server->close($frame->fd);
return;
}
echo "有人发消息,内容:" . $message;
echo "\n";
// 通知其他人 ,进行广播
foreach ($this->table as $row) {
if ($row['fd'] != $frame->fd) {
echo "推送消息:" . $message."给fd:" . $row['fd'] ;
$server->push($row['fd'], json_encode([
'type' => 'my_message',
'message' => $message,
'from_user_name' => $user_name,
]));
}
}
}
}
/**
* 客户端关闭的时候
*
* @param \swoole_websocket_server $server
* @param int $fd
*/
public function close(\swoole_websocket_server $server, int $fd)
{
$user = $this->table->get($fd);
$user_name = $user['user_name'];
echo "有人下线,数据:" . json_encode($user, JSON_UNESCAPED_UNICODE);
$this->table->del($fd);
// 通知其他人 某某 下线了。
foreach ($this->table as $row) {
$server->push($row['fd'], json_encode([
'type' => 'my_id',
'message' => $user_name . ' 下线了',
]));
}
}
WebSocketServer.php 是核心文件。
代码说明
这一版的功能总算象个样子了!
swoole 挺好用的。
效果示例
意外被我发现,原来 PHP 也可以搭建区块链,我用了 6 个月考 PHP 来了解区块链基本低价逻辑,在伙伴怂恿之下也学智能合约 solidiy, 随后发现 web3 搭建区块链比 PHP 更完整,比如 PHP 批量发币又限,仅仅在 40-57 笔(透过 json-rpc, header byte length 不可过大), web3 这可以批量 800 笔以上,再发现可无线创建数冷钱包地址,之后在 swap 合约学股权分配机制,接着 NFT 合约与流程,学完了这些,本来需要花钱用第三方平台来操作的,可以让项目方省下不少。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。