<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
PHP並非不能實現HTTP服務,一般來講,這叫網路程式設計或Socket程式設計。在學習到其他語言的這部分的時候,一般的思路就是如何監聽TCP實現一個伺服器,並處理HTTP協定。
PHP也可以這樣做,同時一般伴隨著高效能這樣的關鍵字出現。
我們可以通過PHP的Socket函數,很簡單的實現出HTTP服務。
function run() { //建立伺服器端的socket套接流,net協定為IPv4,protocol協定為TCP $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); /*繫結接收的套接流主機和埠,與使用者端相對應*/ if(socket_bind($socket,"0.0.0.0", 9502) == false){ echo 'server bind fail:'.socket_strerror(socket_last_error());exit(); } //監聽套接流 if(socket_listen($socket,4)==false){ echo 'server listen fail:'.socket_strerror(socket_last_error());exit(); } //非阻塞 socket_set_nonblock($socket); call_user_func('onAccept',$socket); } run();
然後通過Socket處理收到的資料以及作出響應:
function onMessage($connection) { //拼裝返回的html內容 $content = '<html><title>hello,world</title><body>hello,world,http</body></html>'; //拼裝頭資訊 $header = ''; $header .= "HTTP/1.1 200 OKrn"; $header .= "Date: ".gmdate('D, d M Y H:i:s T')."rn"; $header .= "Content-Type: text/html;charset=utf-8rn"; $header .= "Content-Length: ".strlen($content)."rnrn";//必須2個rn表示頭部資訊結束 $header .= $content; socket_write($connection,$header,strlen($header)); } function onAccept($socket) { //接收使用者端傳遞過來的資訊 while(true) { $accept_resource = socket_accept($socket); if($accept_resource !== false) { $string = socket_read($accept_resource,1024); echo 'server receive is :'.$string.PHP_EOL; if($string != false) { call_user_func('onMessage',$accept_resource); } } } }
實際上,PHP有很多在專案都在實現HTTP伺服器,而且他們一般也都宣稱是高效能的。
Workerman是一款純PHP開發的開源高效能的PHP 應用容器。幾乎能夠實現任何型別的網路程式設計,並且內建了一個HTTP協定。
$worker = new Worker('http://0.0.0.0:1221');
Workerman的官方在21年出品了Webman,一個基於Workerman實現的高效能HTTP服務架構。替代傳統PHP-FPM架構,提供高效能的HTTP服務。可以用來開發網站、介面、微服務。
Webman實際上是一個開發框架,專案的目錄結構都已經設定好了,按照檔案開發就行,最後只要通過命令就能執行起來。
php start.php start
Webman支援是一個MVC框架,支援名稱空間自動載入,所以程式碼像這樣:
<?php namespace appcontroller; use supportRequest; class UserController { public function hello(Request $request) { $default_name = 'webman'; // 從get請求裡獲得name引數,如果沒有傳遞name引數則返回$default_name $name = $request->get('name', $default_name); // 向瀏覽器返回字串 return response('hello ' . $name); } }
除了高效能等特點,他的上手難度很低,並且風格與現代的MVC風格一致,支援PSR標準,程式碼精簡高效。如果你是ThinkPHP的開發者,你會發現很容易上手Webman。
說道高效能HTTP服務,總是繞不開swoole的,他也是國內最早火熱起來的PHP高效能解決方案。
使用swoole實現HTTP服務的程式碼也很簡單:
$http = new SwooleHttpServer('0.0.0.0', 9501); $http->on('Request', function ($request, $response) { $response->header('Content-Type', 'text/html; charset=utf-8'); $response->end('<h1>Hello Swoole. #' . rand(1000, 9999) . '</h1>'); }); $http->start();
swoole實際上是一個PHP的擴充套件,近幾年基於他發展起了很多的高效能框架,比如easyswoole、Hyperf、Swoft、MixPHP等等。它們都基於Swoole實現框架,可以很容易的建立完整度很成熟的系統。
ReactPHP 是用於 PHP 事件驅動程式設計的底層庫。也可以用來實現各類網路程式設計,包括HTTP服務。用它實現HTTP服務也很簡單:
require __DIR__ . '/vendor/autoload.php'; $http = new ReactHttpHttpServer(function (PsrHttpMessageServerRequestInterface $request) { return ReactHttpMessageResponse::plaintext( "Hello World!n" ); }); $socket = new ReactSocketSocketServer('127.0.0.1:8080'); $http->listen($socket); echo "Server running at http://127.0.0.1:8080" . PHP_EOL;
它是一個底層庫,一般而言,所有PSR的框架都可以基於他執行,替換PHP-FPM。所以他也提供了各個流行框架的接入方案,包括laravel、symfony等,基於ReactPHP,開發了一個PHP-PM專案。
PHP-PM 是 PHP 應用程式的程序管理器、增壓器和負載平衡器。
可以直接通過命令執行:
ppm start --bootstrap=laravel --app-env=prod --debug=0 --logging=0 --workers=20
實際上ReactPHP是個很有趣的專案,比如IP電視伺服器、終端shell、Mqtt的server、PHP版的Redis、一個GUI框架、位元幣P2P網路等等,以後有機會給大家介紹介紹。
AMPHP 是 PHP 的高質量、事件驅動庫的集合,在設計時考慮了纖維和並行性。
基於AMPHP實現的HTTP服務架構叫amphp/http-server
。使用它也可以快速實現一個穩定高效能的HTTP服務。
use AmpHttpServerRequestHandlerClosureRequestHandler; use AmpHttpServerSocketHttpServer; use AmpHttpServerRequest; use AmpHttpServerResponse; use AmpHttpStatus; use AmpSocketServer; use PsrLogNullLogger; // Run this script, then visit http://localhost:1337/ in your browser. AmpLoop::run(function () { $sockets = [ Server::listen("0.0.0.0:1337"), Server::listen("[::]:1337"), ]; $server = new SocketHttpServer($sockets, new ClosureRequestHandler(function (Request $request) { return new Response(Status::OK, [ "content-type" => "text/plain; charset=utf-8" ], "Hello, World!"); }), new NullLogger); yield $server->start(); // Stop the server gracefully when SIGINT is received. // This is technically optional, but it is best to call Server::stop(). AmpLoop::onSignal(SIGINT, function (string $watcherId) use ($server) { AmpLoop::cancel($watcherId); yield $server->stop(); }); });
AMPHP也實現了很多有趣的專案,比如Mysql的使用者端,能夠實現連線池等特性。
swow是一個基於協程的跨平臺並行I/O引擎,關注並行IO。
官方給出的HTTP例子程式碼行數比較多,主要是展示了HTTP請求支援的每個階段的操作方法,程式碼也是很簡潔的。
declare(strict_types=1); use SwowBuffer; use SwowCoroutine; use SwowHttpParser; use SwowHttpParserException; use SwowSocket; use SwowSocketException; $host = getenv('SERVER_HOST') ?: '127.0.0.1'; $port = (int) (getenv('SERVER_PORT') ?: 9764); $backlog = (int) (getenv('SERVER_BACKLOG') ?: 8192); $multi = (bool) (getenv('SERVER_MULTI') ?: false); $bindFlag = Socket::BIND_FLAG_NONE; $server = new Socket(Socket::TYPE_TCP); if ($multi) { $server->setTcpAcceptBalance(true); $bindFlag |= Socket::BIND_FLAG_REUSEPORT; } $server->bind($host, $port, $bindFlag)->listen($backlog); while (true) { try { $connection = $server->accept(); } catch (SocketException $exception) { break; } Coroutine::run(static function () use ($connection): void { $buffer = new Buffer(Buffer::COMMON_SIZE); $parser = (new Parser())->setType(Parser::TYPE_REQUEST)->setEvents(Parser::EVENT_BODY); $parsedOffset = 0; $body = null; try { while (true) { $length = $connection->recv($buffer, $buffer->getLength()); if ($length === 0) { break; } while (true) { $parsedOffset += $parser->execute($buffer, $parsedOffset); if ($parser->getEvent() === $parser::EVENT_NONE) { $buffer->truncateFrom($parsedOffset); $parsedOffset = 0; break; /* goto recv more data */ } if ($parser->getEvent() === Parser::EVENT_BODY) { $body ??= new Buffer(Buffer::COMMON_SIZE); $body->write(0, $buffer, $parser->getDataOffset(), $parser->getDataLength()); } if ($parser->isCompleted()) { $response = sprintf( "HTTP/1.1 200 OKrn" . "Connection: %srn" . "Content-Length: %drnrn" . '%s', $parser->shouldKeepAlive() ? 'Keep-Alive' : 'Closed', $body ? $body->getLength() : 0, $body ?: '' ); $connection->send($response); $body?->clear(); break; /* goto recv more data */ } } if (!$parser->shouldKeepAlive()) { break; } } } catch (SocketException $exception) { echo "No.{$connection->getFd()} goaway! {$exception->getMessage()}" . PHP_EOL; } catch (ParserException $exception) { echo "No.{$connection->getFd()} parse error! {$exception->getMessage()}" . PHP_EOL; } $connection->close(); }); }
以上是一些非常流行的PHP框架和專案,但還有其他很多實現了高效能HTTP服務的專案。這裡不多做介紹了。雖然我們談到PHP的時候,很少談到網路程式設計,甚至在入門教學中根本就沒有網路程式設計這節課。但是使用PHP做網路程式設計的各項應用已經很火熱了。
在入門其他語言是一定有一節課程是學習網路程式設計的,做PHP教學的也應該考慮考慮增加這部分課程了。
到此這篇關於詳解PHP實現HTTP伺服器過程的文章就介紹到這了,更多相關PHP HTTP伺服器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45