摘要:理論主要介紹下實現一個網絡服務器的基本步驟,代碼會在實踐環節復現一次。第一步我們需要創建一個,綁定服務器端口,監聽端口,在中用一個函數就能完成上面個步驟。此時程序會進入睡眠狀態,直到有新的客戶端發起到服務器,操作系統會喚醒此進程。
概述
想要更好的理解,網絡編程,寫出一個高性能的服務,我們需要花點時間來理解下對于服務器處理客戶端的整個流程并且理解一些關鍵的術語,本來想在本文中補充一些基礎理論知識,擔心篇幅過長不利于閱讀,所以以后補發一些基礎知識,接下來進入正題。
理論主要介紹下實現一個網絡服務器的基本步驟,代碼會在實踐環節復現一次。
第一步我們需要創建一個socket,綁定服務器端口(bind),監聽端口(listen),在PHP中用stream_socket_server一個函數就能完成上面3個步驟。
第二步進入while循環,阻塞在accept操作上,等待客戶端連接進入。此時程序會進入睡眠狀態,直到有新的客戶端發起connect到服務器,操作系統會喚醒此進程。accept函數返回客戶端連接的socket
第三步利用fread讀取客戶端socket當中的數據收到數據后服務器程序進行處理然后使用fwrite向客戶端發送響應。長連接的服務會持續與客戶端交互,而短連接服務一般收到響應就會close。
實踐在這里我們用代碼來實現下基本一個流程,在開始寫代碼之前介紹介幾個php函數,是我們代碼中可能會用到的,方便大家理解。
函數stream_socket_server
stream_socket_accept
call_user_func
is_callable
fread
點擊函數了解用法代碼
廢話少說直接開擼~
onConnect = function ($data) { echo "新的連接來了", $data, PHP_EOL; }; //提前注冊了一個接收消息事件回調 $worker->onMessage = function ($conn, $message) { }; $worker->run();
按照之前的流程我們需要監聽端口+地址
public function __construct($socket_address) { //監聽地址+端口 $this->socket=stream_socket_server($socket_address); }
下一步就需要阻塞在accept操作,等待客戶端連接進入。此時程序會進入睡眠狀態,直到有新的客戶端發起connect到服務器,操作系統會喚醒此進程
public function run(){ while (true) { //循環監聽 $client = stream_socket_accept($this->socket);//在服務端阻塞監聽 } }
當新的連接進入喚醒進程并且觸發連接事件回調
public function run(){ while (true) { //循環監聽 $client = stream_socket_accept($this->socket);//在服務端阻塞監聽 if(!empty($client) && is_callable($this->onConnect)){//socket連接成功并且是我們的回調 //觸發事件的連接的回調 call_user_func($this->onConnect,$client); } } }
這里的連接回調實際上觸發的就是之前準備好類庫的這里下面這段代碼
$worker->onConnect = function ($data) { echo "連接事件:", $data, PHP_EOL; };
當連接成功后利用fread獲取到客戶端的內容,并觸發接收消息事件
public function run(){ while (true) { //循環監聽 $client = stream_socket_accept($this->socket);//在服務端阻塞監聽 if(!empty($client) && is_callable($this->onConnect)){//socket連接成功并且是我們的回調 //觸發事件的連接的回調 call_user_func($this->onConnect,$client); } //從連接中讀取客戶端內容 $buffer=fread($client,65535);//參數2:在緩沖區當中讀取的最大字節數 //正常讀取到數據。觸發消息接收事件,進行響應 if(!empty($buffer) && is_callable($this->onMessage)){ //觸發時間的消息接收事件 call_user_func($this->onMessage,$this,$client,$buffer);//傳遞到接收消息事件》當前對象、當前連接、接收到的消息 } } }
到此處基本的一個網絡服務接收基本完成,還需要對請求做出一個響應,以HTTP請求為例,這里封裝了一個http響應的方法(http://127.0.0.1:9810)
class Worker{ ... ... ... public function send($conn,$content){ $http_resonse = "HTTP/1.1 200 OK "; $http_resonse .= "Content-Type: text/html;charset=UTF-8 "; $http_resonse .= "Connection: keep-alive "; $http_resonse .= "Server: php socket server "; $http_resonse .= "Content-length: ".strlen($content)." "; $http_resonse .= $content; fwrite($conn, $http_resonse); } }
當觸發接收消息事件時對http請求做出響應
$worker->onMessage = function ($server,$conn, $message) { echo "來自客戶端消息:",$message,PHP_EOL; $server->send($conn,"來自服務端消息"); };
到這就結束了~,完整代碼直通車
缺點一次只能處理一個連接,不支持多個連接同時處理
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30170.html
摘要:如需了解更多物聯網網絡編程知識請點擊物聯網云端開發武器庫物聯網高并發編程之網絡編程中的線程模型值得說明的是,具體選擇線程還是進程,更多是與平臺及編程語言相關。 如需了解更多物聯網網絡編程知識請點擊:物聯網云端開發武器庫 物聯網高并發編程之網絡編程中的線程模型 值得說明的是,具體選擇線程還是進程,更多是與平臺及編程語言相關。例如 C 語言使用線程和進程都可以(例如 Nginx 使用進程...
摘要:協作方式在高并發場景中,必須要讓服務器同時維護大量請求連接,可能是一個服務進程創建另一個進程,也可能是一個服務線程去創建另一個線程,但連接結束后進程或線程就銷毀了,這是一個巨大的浪費一個自然的想法就是通過創建一個進程線程池從而達到資源復用, showImg(https://segmentfault.com/img/bVbtgn1?w=313&h=208); 協作方式 在高并發場景中,必...
摘要:一閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應結果發給相應的連接請求處理完成因為基于,所以每個可以處理無數個連接請求。如此,就輕松的處理了高并發。 一、閱前熱身 為了更加形象的說明同步異步、阻塞非阻塞,我們以小明去買奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點在消息通知的方式上...
摘要:一閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應結果發給相應的連接請求處理完成因為基于,所以每個可以處理無數個連接請求。如此,就輕松的處理了高并發。 一、閱前熱身 為了更加形象的說明同步異步、阻塞非阻塞,我們以小明去買奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點在消息通知的方式上...
閱讀 683·2021-11-22 09:34
閱讀 3822·2021-09-22 15:42
閱讀 1327·2021-09-03 10:28
閱讀 1072·2021-08-26 14:13
閱讀 1901·2019-08-29 15:41
閱讀 1423·2019-08-29 14:12
閱讀 3364·2019-08-26 18:36
閱讀 3307·2019-08-26 13:47