首页
下载
文档
社区
视频
捐赠
源代码
赞助商
AOT 编译器
AI 助理
商业产品
PHP AOT 原生编译器
Swoole-Compiler 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
关于sendfile发送文件的一些疑问,还请知道的大佬赐教
### 问题描述 http中使用sendfile发送文件时,是不是无法处理其他请求? 弄了一个视频播放页面,用到sendfile发送视频文件,在本地测试时没问题,视频瞬间就能播放出来,也能响应其他请求。但是放到网络上时,由于网速慢,视频迟迟无法播放出来,然后其他请求也无法响应。关闭视频播放页面也无法解决,其他请求任然无法响应。只有重启服务端。 ### Swoole版本,PHP版本,以及操作系统版本信息 ### 相关代码 ```php <?php define('ZSSL',0); if(ZSSL){ $http = new Swoole\Http\Server('0.0.0.0', 9588,SWOOLE_PROCESS,SWOOLE_SOCK_TCP|SWOOLE_SSL); }else{ $http = new Swoole\Http\Server('0.0.0.0', 9588); } $http->on('start', function ($server) { echo "Swoole http server is started at http://0.0.0.0:9588\n"; }); $h=<<<HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>mp4</title> </head> <body> <video width="600" height="500" controls> <source src="m.php" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video> </body> </html> HTML; $http->on('request', function ($req, $res)use($h) { //print_r($req->server); if($req->server['request_uri']=='/p.php'){ $res->header('Content-Type', 'text/html; charset=utf-8'); $res->end($h); }elseif($req->server['request_uri']=='/m.php'){ $f_size=filesize('m.mp4'); $start_byte = 0; $end_byte = $f_size; $range = $req->header['range'] ?? false; if ($range) { $range_ls = explode('-', str_replace('=', '', strstr($range, '='))); $start_byte = $range_ls[0]; $end_byte = $range_ls[1]; if($start_byte==''){$start_byte=$f_size-$end_byte+1;} if($end_byte==''){$end_byte = $f_size;} $res->header("Content-Length",$end_byte-$start_byte); $res->status(206); $res->header("Content-Range", 'bytes '.$start_byte.'-'.($end_byte-1).'/'.$f_size); }else{ $res->header("Content-Length", $f_size); } $res->header('Content-Type', 'video/mp4'); $res->sendfile('m.mp4',$start_byte,$end_byte-$start_byte); }else{ $res->header('Content-Type', 'text/html; charset=utf-8'); if(isset($req->get['h'])){ $res->end('url:'.$req->server['request_uri'].'<br>swoole:'.$req->get['h']); }else{ $res->end('url:'.$req->server['request_uri'].'<br>swoole:'); } } }); $conf=array( 'reactor_num' =>1, 'worker_num'=>1, 'max_request'=>0, 'buffer_input_size' =>2 * 1024 * 1024, 'buffer_output_size'=>2 * 1024 *1024, 'socket_buffer_size'=>2 * 1024 *1024, 'package_max_length'=>2 * 1024 *1024, 'dispatch_mode'=>2, 'message_queue_key'=>'', 'daemonize'=>0, 'ssl_cert_file' => 'm.crt', 'ssl_key_file' => 'private.key', 'open_http2_protocol' => true, ); if(!ZSSL){ unset($conf['ssl_cert_file']); unset($conf['ssl_key_file']); unset($conf['open_http2_protocol']); } $http->set($conf); $http->start(); ``` ### 你期待的结果是什么?实际看到的错误信息又是什么?
发布于4年前 · 26 次浏览 · 来自
提问
li_jun
### 问题描述 http中使用sendfile发送文件时,是不是无法处理其他请求? 弄了一个视频播放页面,用到sendfile发送视频文件,在本地测试时没问题,视频瞬间就能播放出来,也能响应其他请求。但是放到网络上时,由于网速慢,视频迟迟无法播放出来,然后其他请求也无法响应。关闭视频播放页面也无法解决,其他请求任然无法响应。只有重启服务端。 ### Swoole版本,PHP版本,以及操作系统版本信息 ### 相关代码 ```php <?php define('ZSSL',0); if(ZSSL){ $http = new Swoole\Http\Server('0.0.0.0', 9588,SWOOLE_PROCESS,SWOOLE_SOCK_TCP|SWOOLE_SSL); }else{ $http = new Swoole\Http\Server('0.0.0.0', 9588); } $http->on('start', function ($server) { echo "Swoole http server is started at http://0.0.0.0:9588\n"; }); $h=<<<HTML <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>mp4</title> </head> <body> <video width="600" height="500" controls> <source src="m.php" type="video/mp4"> 您的浏览器不支持 HTML5 video 标签。 </video> </body> </html> HTML; $http->on('request', function ($req, $res)use($h) { //print_r($req->server); if($req->server['request_uri']=='/p.php'){ $res->header('Content-Type', 'text/html; charset=utf-8'); $res->end($h); }elseif($req->server['request_uri']=='/m.php'){ $f_size=filesize('m.mp4'); $start_byte = 0; $end_byte = $f_size; $range = $req->header['range'] ?? false; if ($range) { $range_ls = explode('-', str_replace('=', '', strstr($range, '='))); $start_byte = $range_ls[0]; $end_byte = $range_ls[1]; if($start_byte==''){$start_byte=$f_size-$end_byte+1;} if($end_byte==''){$end_byte = $f_size;} $res->header("Content-Length",$end_byte-$start_byte); $res->status(206); $res->header("Content-Range", 'bytes '.$start_byte.'-'.($end_byte-1).'/'.$f_size); }else{ $res->header("Content-Length", $f_size); } $res->header('Content-Type', 'video/mp4'); $res->sendfile('m.mp4',$start_byte,$end_byte-$start_byte); }else{ $res->header('Content-Type', 'text/html; charset=utf-8'); if(isset($req->get['h'])){ $res->end('url:'.$req->server['request_uri'].'<br>swoole:'.$req->get['h']); }else{ $res->end('url:'.$req->server['request_uri'].'<br>swoole:'); } } }); $conf=array( 'reactor_num' =>1, 'worker_num'=>1, 'max_request'=>0, 'buffer_input_size' =>2 * 1024 * 1024, 'buffer_output_size'=>2 * 1024 *1024, 'socket_buffer_size'=>2 * 1024 *1024, 'package_max_length'=>2 * 1024 *1024, 'dispatch_mode'=>2, 'message_queue_key'=>'', 'daemonize'=>0, 'ssl_cert_file' => 'm.crt', 'ssl_key_file' => 'private.key', 'open_http2_protocol' => true, ); if(!ZSSL){ unset($conf['ssl_cert_file']); unset($conf['ssl_key_file']); unset($conf['open_http2_protocol']); } $http->set($conf); $http->start(); ``` ### 你期待的结果是什么?实际看到的错误信息又是什么?
赞
0
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
登录
后参与评论
评论
2022-06-18
li_jun
补充,通过系统流量观测发现,就算关闭播放页面,文件应该任然在发送,有流量在跑(此时没有其他操作),关闭服务端后,流量就降成了0
赞
0
回复
2022-06-30
Rango
信息比较少,很难判断,关闭连接之后会停止发送的。 建议使用 tcpdump、strace、gdb 等工具追踪一下。
赞
0
回复
2022-07-07
li_jun
回复
Rango
老大我提交了代码,你试试看能不能复现问题,访问p.php播放视频时,再访问kk.php就会出现kk.php无法响应的情况,m.mp4是一个近2G的视频文件,本地与内网没问题,远程服务器就会出问题,网速大概是100-200kb/s,http模式下情况要好一点,访问kk.php偶尔能响应,https模式下问题更明显,浏览器关闭p.php播放页面后问题持续,需要ctrl+c关闭服务端后重启,php版本8.0.1,swoole版本4.8.9,浏览器是火狐
赞
0
回复
2022-07-09
Rango
回复
li_jun
收到,我试试能否重现
赞
0
回复
2022-07-21
Rango
回复
li_jun
请添加一下识沃客服,然后拉个群,沟通一下细节吧
赞
0
回复
2022-07-29
Rango
关闭`http2`,由于`http2`有流控管理,`sendfile`可能会导致发送窗口耗尽,导致其他请求也不被处理了。
赞
0
回复