首页
下载
文档
问答社区
视频
捐赠
源代码
AI 助理
赞助商
CRMEB
Apipost
腾讯云
微擎
禅道
51Talk
商业产品
Swoole AI 智能文档翻译器
Swoole-Compiler PHP 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
Swoole Client 运行一段时间后接收不到消息
### 问题描述 tcp client 运行一段时间后就开始接收不到消息,但是用tcpdump抓包是可以看到消息已经过来了的。使用 golang 写client同时订阅,一开始 swoole 和 golang 都可以收到,过了一段时间 swoole 就收不到了,golang 可以正常收到,抓包发现数据也是过来了的。 重启 client 可以恢复正常,但是过段时间又会出现同样的问题。 server 端 swoole 写的广播程序,会不断给订阅了的 client 广播数据。 ### Swoole版本,PHP版本,以及操作系统版本信息 swoole: 4.8.0 php: 7.4.24 os: 用的hyperf,镜像是:hyperf/hyperf:7.4-alpine-v3.11-swoole ### 相关代码 将此代码作为process运行。 TcpRegisterProcess.php: ```php <?php /** * Created by * Author purelight * Date 2021/10/19 * Time 3:26 下午 */ namespace App\Process; use App\Log\Log; use App\Service\EncodeService; use App\Service\RedisService; use Hyperf\Di\Annotation\Inject; use Hyperf\Process\AbstractProcess; use Swoole\Client; class TcpRegisterProcess extends AbstractProcess { /** * @Inject() * @var EncodeService */ protected $encoder; /** * @Inject() * @var RedisService */ protected $redisService; public function handle_bak(): void { $log = Log::get('app', 'ds'); $client = new Client(SWOOLE_SOCK_TCP | SWOOLE_KEEP); $client->set([ 'open_length_check' => true, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4, 'package_max_length' => 65535, ]); if (!$client->connect(config('register_host'), (int)config('register_port'), 5)) { $log->error('register tcp connect fail'); return; } $res = $client->send($this->encoder->encode('subscribe')); $log->info('tcp register 订阅成功('.var_export($res,true).'):'.json_encode($client->getsockname())); while (true) { $row = $client->recv(); $log->error('tcp recv:'.var_export($row,true)); if (false === $row){ if ($client->errCode !== SOCKET_EAGAIN){ $log->error($client->errCode); } } elseif ($row !== '') { $msg = $this->encoder->decode($row); if (false !== $msg) { $this->redisService->handleTransfer($msg); } }else{ $log->error('tcp异常:'.var_export($row,true).',client:'.json_encode($client->getsockname())); continue; } sleep(0.1); } } public function handle(): void { $log = Log::get('app','ds'); $client = new \Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); $client->set([ 'open_length_check' => true, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4, 'package_max_length' => 65535, ]); if (!$client->connect(config('register_host'), (int)config('register_port'), 5)) { $log->error('register tcp connect fail'); return; } $res = $client->send($this->encoder->encode('subscribe')); $log->info('tcp register 订阅成功('.var_export($res,true).'):'.json_encode($client->getsockname())); while (true) { $row = $client->recv(5.0); $log->error('tcp recv:'.var_export($row,true)); if (false === $row){ $log->error('false ==> '.swoole_strerror($client->errCode,9)); } elseif ($row !== '') { $msg = $this->encoder->decode($row); if (false !== $msg) { $this->redisService->handleTransfer($msg); } }else{ $log->error('tcp异常,重启进程:'.var_export($row,true).',client:'.json_encode($client->getsockname())); break; } } } } ``` EncodeService.php: ```php <?php /** * Created by * Author purelight * Date 2021/10/19 * Time 3:37 下午 */ namespace App\Service; class EncodeService { public function encode(string $msg) { $length = strlen($msg); $header = pack('N',$length); return $header.$msg; } public function decode(string $row) { $data = unpack('N',$row); if (false === $data){ return false; } return substr($row,4,$data[1]); } } ``` 服务端主要代码逻辑(不重要,这部分没有问题): ```php public function broadcastMsg(string $msg) { $instances = $this->redis->sMembers(self::KEY_REGISTER_SERVERS); if (empty($instances)){ return; } $log = Log::get('app','register'); $log->info('start broadcast'); $container = ApplicationContext::getContainer(); $server = $container->get(\Swoole\Server::class); foreach ($instances as $instance){ $rs = $server->send((int)$instance,$this->encoder->encode($msg)); $log->error(var_export($rs,true)); } $log->info('end broadcast'); } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 期待的结果是稳定收数据,刚启动的时候一切正常,过段时间收不到数据,同时使用 tcpdump 抓包发现数据已经过来了,$client->recv(5.0) 返回 false 超时,就像真的没有数据一样,求解~
发布于3年前 · 23 次浏览 · 来自
提问
purelight
### 问题描述 tcp client 运行一段时间后就开始接收不到消息,但是用tcpdump抓包是可以看到消息已经过来了的。使用 golang 写client同时订阅,一开始 swoole 和 golang 都可以收到,过了一段时间 swoole 就收不到了,golang 可以正常收到,抓包发现数据也是过来了的。 重启 client 可以恢复正常,但是过段时间又会出现同样的问题。 server 端 swoole 写的广播程序,会不断给订阅了的 client 广播数据。 ### Swoole版本,PHP版本,以及操作系统版本信息 swoole: 4.8.0 php: 7.4.24 os: 用的hyperf,镜像是:hyperf/hyperf:7.4-alpine-v3.11-swoole ### 相关代码 将此代码作为process运行。 TcpRegisterProcess.php: ```php <?php /** * Created by * Author purelight * Date 2021/10/19 * Time 3:26 下午 */ namespace App\Process; use App\Log\Log; use App\Service\EncodeService; use App\Service\RedisService; use Hyperf\Di\Annotation\Inject; use Hyperf\Process\AbstractProcess; use Swoole\Client; class TcpRegisterProcess extends AbstractProcess { /** * @Inject() * @var EncodeService */ protected $encoder; /** * @Inject() * @var RedisService */ protected $redisService; public function handle_bak(): void { $log = Log::get('app', 'ds'); $client = new Client(SWOOLE_SOCK_TCP | SWOOLE_KEEP); $client->set([ 'open_length_check' => true, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4, 'package_max_length' => 65535, ]); if (!$client->connect(config('register_host'), (int)config('register_port'), 5)) { $log->error('register tcp connect fail'); return; } $res = $client->send($this->encoder->encode('subscribe')); $log->info('tcp register 订阅成功('.var_export($res,true).'):'.json_encode($client->getsockname())); while (true) { $row = $client->recv(); $log->error('tcp recv:'.var_export($row,true)); if (false === $row){ if ($client->errCode !== SOCKET_EAGAIN){ $log->error($client->errCode); } } elseif ($row !== '') { $msg = $this->encoder->decode($row); if (false !== $msg) { $this->redisService->handleTransfer($msg); } }else{ $log->error('tcp异常:'.var_export($row,true).',client:'.json_encode($client->getsockname())); continue; } sleep(0.1); } } public function handle(): void { $log = Log::get('app','ds'); $client = new \Swoole\Coroutine\Client(SWOOLE_SOCK_TCP); $client->set([ 'open_length_check' => true, 'package_length_type' => 'N', 'package_length_offset' => 0, 'package_body_offset' => 4, 'package_max_length' => 65535, ]); if (!$client->connect(config('register_host'), (int)config('register_port'), 5)) { $log->error('register tcp connect fail'); return; } $res = $client->send($this->encoder->encode('subscribe')); $log->info('tcp register 订阅成功('.var_export($res,true).'):'.json_encode($client->getsockname())); while (true) { $row = $client->recv(5.0); $log->error('tcp recv:'.var_export($row,true)); if (false === $row){ $log->error('false ==> '.swoole_strerror($client->errCode,9)); } elseif ($row !== '') { $msg = $this->encoder->decode($row); if (false !== $msg) { $this->redisService->handleTransfer($msg); } }else{ $log->error('tcp异常,重启进程:'.var_export($row,true).',client:'.json_encode($client->getsockname())); break; } } } } ``` EncodeService.php: ```php <?php /** * Created by * Author purelight * Date 2021/10/19 * Time 3:37 下午 */ namespace App\Service; class EncodeService { public function encode(string $msg) { $length = strlen($msg); $header = pack('N',$length); return $header.$msg; } public function decode(string $row) { $data = unpack('N',$row); if (false === $data){ return false; } return substr($row,4,$data[1]); } } ``` 服务端主要代码逻辑(不重要,这部分没有问题): ```php public function broadcastMsg(string $msg) { $instances = $this->redis->sMembers(self::KEY_REGISTER_SERVERS); if (empty($instances)){ return; } $log = Log::get('app','register'); $log->info('start broadcast'); $container = ApplicationContext::getContainer(); $server = $container->get(\Swoole\Server::class); foreach ($instances as $instance){ $rs = $server->send((int)$instance,$this->encoder->encode($msg)); $log->error(var_export($rs,true)); } $log->info('end broadcast'); } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? 期待的结果是稳定收数据,刚启动的时候一切正常,过段时间收不到数据,同时使用 tcpdump 抓包发现数据已经过来了,$client->recv(5.0) 返回 false 超时,就像真的没有数据一样,求解~
赞
0
分享
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
评论
还没有评论!
微信公众号
热门内容
暂无回复的问答
- CodeGalaxy K3s 轻量集群节点之间如何实现负载均衡
- 关于openssl CURL WARNING swSSL_connect: SSL_connect(fd=69) failed. Error: error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small[1|394]
- 多个模型如何进行事务异常回退?
- websocket开启wss报错
- 协程tcp服务器如何使用多进程?recv()方法接收信息,打印出来的pid一直是同一个。没用使用到多进程啊。