iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >workerman怎么自定义协议解决粘包拆包问题
  • 944
分享到

workerman怎么自定义协议解决粘包拆包问题

2023-07-04 19:07:13 944人浏览 安东尼
摘要

这篇“workerman怎么自定义协议解决粘包拆包问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“workerman怎么自

这篇“workerman怎么自定义协议解决粘包拆包问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“workerman怎么自定义协议解决粘包拆包问题”文章吧。

问题解答:

关于网游的通信数据包格式的约定,我在网上也看过一些。如果不是用弱类型语言做服务端脚本,其实别人常用的是字节数组。但是 PHP 在接收到字节数组时,其实就是字符串,但前提时该字节数组没有一些特定转换的。就拿 C# 来说,在解决粘包等问题会在字节数组前加入字节长度 (BitConverter.GetBytes (len))。但是这个传递到 php 服务端接收时,字符串前 4 个字节就是显示不出来,用过很多方法进行转换都取不出来。 后来也想过用 Protobuf 数据方式,虽然 PHP 可以对数据可以转换,但是客户端 C# 我还不太熟就放弃了。

还一个问题是,其实别人做网游服务端实现帧同步大部分都是 UDP 协议,同时也有 tcp 和 UDP 共用。但是如果只是小型多人在线游戏,用 PHP 做服务端,TCP 协议通信也完全可以的。接下来就回到 workerman 的自定义协议和粘包拆包问题吧。

自定义协议:

workerman 对 PHP 的几个 Socket 函数进行了封装 (关于 socket 函数,如果愿意折腾,php 也可以写一个文件传输的小工具的),基于 TCP 之上也自带了几个应用层协议,比如 Http, websocket, Frame 等。也预留了用户自行定义协议的路口,只需要实现他的 ProtocolInterface 接口,以下就简单介绍以下接口需要实现的几个方法。

1.  Input 方法

在这个方法里,可以在服务端接收前对数据包进行解包,检查包长度,过滤等。返回 0 就将数据包放入接收端的缓冲内继续等待,返回指定长度则表示取出缓冲区内长度。如果异常也可以返回 false 直接关闭该客户端连接。

2. encode 方法

该方法是服务端在发送数据包到客户端前,对数据包格式的处理,也就是封包,这个就要前后端约定好了。

3. decode 方法

这个方法也就是解包,就是从缓冲区里取出指定长度到 onMessage 接收前要进行处理的地方,比如进行逻辑调配等等。

粘包拆包产生现象:

由于 TCP 是基于流的,且因为是传输层,在上层的应用通过 socket 套接字 (理解为接口) 通信时,他不知道传递过来的数据包开头结尾在哪。只是根据 TCP 的一套拥塞算法机型粘合或拆解的发送。所以从字面上看,粘包就是几个数据包一起发送,原本应该是两个包,客户端只收到了一个包。而拆包是将一个数据包拆成了几个包,本应该是接收一个数据包,却只收到了一个。所以如果不解决这个,前面提到了按约定字符串传输,就可能解包时报错的情况。

粘包拆包解决方法:

1. 首部加数据包长度

<?phpnamespace Workerman\Protocols;use Workerman\Connection\TcpConnection;class Game{        public static function input($buffer, TcpConnection $connection)    {        // 数据包前4个字节        $bodyLen = intval(substr($buffer, 0 , 4));        $totalLen = strlen($buffer);        if ($totalLen < 4) {            return 0;        }        if ($bodyLen <= 0) {            return 0;        }        if ($bodyLen > strlen(substr($buffer, 4))) {            return 0;        }        return $bodyLen + 4;    }        public static function decode($buffer)    {        return substr($buffer, 4);    }        public static function encode($buffer)    {        // 对数据包长度向左补零        $bodyLen = strlen($buffer);        $headerStr = str_pad($bodyLen, 4, 0, STR_PAD_LEFT);        return $headerStr . $buffer;    }}

2. 特定字符分割

<?phpnamespace Workerman\Protocols;use Workerman\Connection\ConnectionInterface;class Tank{        public static function input($buffer, ConnectionInterface $connection)    {                if (isset($connection->maxPackageSize) && \strlen($buffer) >= $connection->maxPackageSize) {            $connection->close();            return 0;        }                $pos = \strpos($buffer, "#");                if ($pos === false) {            return 0;        }                // 返回当前包长        return $pos + 1;    }        public static function encode($buffer)    {        return $buffer . "#";    }        public static function decode($buffer)    {        return \rtrim($buffer, "#");    }}

粘包拆包测试:

这里就只演示特定字符串分割的解决方法,因为上面首页 4 字节加包长的还是存在问题。就是第一次发送不带包长,后面模拟粘包还是拆包都会停留在缓冲区,下面演示可以参照上面代码查看。

1. 服务开启和客户端连接

2. 服务业务端代码

数据包格式说明一下,字符串以逗号分割,数据包以 #分割,逗号分割第一组是业务方法,如 Login 表示登陆传递,Pos 表示坐标传递,后面带的就是对应方法需要的参数了。

<?phpuse Workerman\Worker;require_once __DIR__ . '/vendor/autoload.php';// #### create socket and listen 1234 port ####$worker = new Worker('tank://0.0.0.0:1234');// 4 processes//$worker->count = 4;$worker->onWorkerStart = function ($connection) {    echo "游戏协议服务启动……";};// Emitted when new connection come$worker->onConnect = function ($connection) {    echo "New Connection\n";    $connection->send("address: " . $connection->getRemoteIp() . " " . $connection->getRemotePort());};// Emitted when data received$worker->onMessage = function ($connection, $data) use ($worker, $stream) {    echo "接收的数据:" . $data . "\n";    // 简单实现接口分发    $arr = explode(",", $data);    if (!is_array($arr) || !count($arr)) {        $connection->close("数据格式错误", true);    }    $func = strtoupper($arr[0]);    $client = $connection->getRemoteAddress();    switch($func) {        case "LOGIN":            $sendData = "Login1";            break;        case "POS":            $positionX = $arr[1] ?? 0;            $positionY = $arr[2] ?? 0;            $positionZ = $arr[3] ?? 0;            $sendData = "POS,$client,$positionX,$positionY,$positionZ";            break;    }    $connection->send($sendData);};// Emitted when connection is closed$worker->onClose = function ($connection) {    echo "Connection closed\n";};// 接收缓冲区溢出回调$worker->onBufferFull = function ($connection) {    echo "清理缓冲区吧";};Worker::runAll();?>

3. 粘包测试

只需要在客户端模拟两个数据包连在一起,但是要以 #分隔,看看服务端接收的时候是一几个包进行处理的。

4. 拆包测试

拆包模拟只需要将一个数据包分成两次发送,看看服务端接收的时候能不能显示或者说能不能按约定好的格式正确显示。

以上就是关于“workerman怎么自定义协议解决粘包拆包问题”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网精选频道。

--结束END--

本文标题: workerman怎么自定义协议解决粘包拆包问题

本文链接: https://www.lsjlt.com/news/346917.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • workerman怎么自定义协议解决粘包拆包问题
    这篇“workerman怎么自定义协议解决粘包拆包问题”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“workerman怎么自...
    99+
    2023-07-04
  • workerman 自定义的协议如何解决粘包拆包
    前言:         由于最近在使用 workerman 实现 Unity3D 联机游戏的服务端,虽然也可以通过 TCP 协议直接通信,但是在实际测试的过程中发现了一些小问题。         比如双方的数据包都是字符串的方式吗,还有就因...
    99+
    2023-09-07
    TCP粘包拆包 workerman unity3d PHP网游服务
  • Golang通过包长协议处理TCP粘包的问题解决
    目录tcp粘包现象代码重现tcp粘包问题处理方法tcp粘包产生的原因这里就不说了,因为大家能搜索TCP粘包的处理方法,想必大概对TCP粘包有了一定了解,所以我们直接从处理思路开始讲起...
    99+
    2024-04-02
  • 云服务器自定义协议丢包怎么解决
    云服务器自定义协议丢包问题的解决方法如下:1. 检查网络质量:首先,确认网络质量是否稳定。可以使用网络监测工具(如ping命令)测试...
    99+
    2023-08-08
    云服务器
  • 解决TCP粘包/拆包问题的方法及示例
    TCP粘包和拆包是网络编程中常见的问题,特别是在数据传输的过程中,可能会发生将多个数据包粘在一起或将一个数据包拆成多个数据包的情况,这可能会导致应用程序无法正确解析数据,从而造成数据错误或系统故障。本文将介绍TCP粘包和拆包的原因、解决方案...
    99+
    2023-09-25
    网络 服务器 tcp/ip c# 网络协议
  • python socket粘包问题怎么解决
    今天小编给大家分享一下python socket粘包问题怎么解决的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我...
    99+
    2024-04-02
  • 如何解决vue-cli 打包后自定义动画未执行的问题
    这篇文章将为大家详细讲解有关如何解决vue-cli 打包后自定义动画未执行的问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。在vue项目中,想实现无缝向上滚动的自定义动...
    99+
    2024-04-02
  • spring注解在自定义jar包中无法被扫描的问题如何解决
    这篇文章主要介绍“spring注解在自定义jar包中无法被扫描的问题如何解决”,在日常操作中,相信很多人在spring注解在自定义jar包中无法被扫描的问题如何解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答...
    99+
    2023-06-20
  • uniapp自定义组件打包后不显示怎么解决
    随着前端开发技术的日新月异,越来越多的开发者选择使用uniapp框架进行多端开发。然而在使用uniapp自定义组件时,有时我们会遇到打包后组件不显示的问题。接下来,我们就来详细了解一下uniapp自定义组件打包后不显示的解决方法。在开始解决...
    99+
    2023-05-14
  • 怎么用java解决背包问题
    背包问题是一个经典的组合优化问题,可以使用动态规划来解决。以下是使用Java语言解决背包问题的一个示例: public class ...
    99+
    2023-10-24
    java
  • Maven打包没有指定主类问题怎么解决
    本文小编为大家详细介绍“Maven打包没有指定主类问题怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“Maven打包没有指定主类问题怎么解决”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Maven打包没有...
    99+
    2023-07-06
  • Mybatis中自定义实例化SqlSessionFactoryBean问题怎么解决
    本篇内容介绍了“Mybatis中自定义实例化SqlSessionFactoryBean问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所...
    99+
    2023-07-05
  • 微信小程序自定义tabbar问题怎么解决
    这篇文章主要介绍“微信小程序自定义tabbar问题怎么解决”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“微信小程序自定义tabbar问题怎么解决”文章能帮助大家解决问题。1、首先按照官方组件在app...
    99+
    2023-06-29
  • css-loader打包出问题怎么解决
    这篇文章主要讲解了“css-loader打包出问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“css-loader打包出问题怎么解决”吧! 各种...
    99+
    2024-04-02
  • springBoot mybatis包扫描问题怎么解决
    这篇文章主要介绍了springBoot mybatis包扫描问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇springBoot mybatis包扫描问题怎么解决文章都会有所收获,下面我们一起来看看吧...
    99+
    2023-06-08
  • 怎么解决Pytorch 自定义子Module .cuda() tensor失败问题
    不懂怎么解决Pytorch 自定义子Module .cuda() tensor失败问题?其实想解决这个问题也不难,下面让小编带着大家一起学习怎么去解决,希望大家阅读完这篇文章后大所收获。在刚从tensorflow转入pytorch,对于自定...
    99+
    2023-05-30
  • c#闭包出现的问题怎么解决
    在C#中,闭包可能会引发内存泄漏或者变量捕获不正确的问题,可以通过以下方法来解决: 手动解除闭包引用:在闭包中,确保不再需要引用...
    99+
    2024-04-02
  • JAVA高并发丢包问题怎么解决
    在Java中解决高并发丢包问题,可以采取以下几种方式:1. 增加服务器端的资源:可以通过增加服务器的带宽、内存和处理能力来缓解高并发...
    99+
    2023-08-19
    JAVA
  • vue自定义组件@click点击失效问题怎么解决
    这篇文章主要讲解了“vue自定义组件@click点击失效问题怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue自定义组件@click点击失效问题怎么解决”吧!自定义组件@click...
    99+
    2023-06-30
  • 自定义过滤器获取不到session问题怎么解决
    今天给大家介绍一下自定义过滤器获取不到session问题怎么解决。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。自定义过滤器获取不到session根本原因,多个...
    99+
    2023-06-26
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作