成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

(一)如何實(shí)現(xiàn)一個(gè)單進(jìn)程阻塞的網(wǎng)絡(luò)服務(wù)器

xiao7cn / 813人閱讀

摘要:理論主要介紹下實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)服務(wù)器的基本步驟,代碼會在實(shí)踐環(huán)節(jié)復(fù)現(xiàn)一次。第一步我們需要?jiǎng)?chuàng)建一個(gè),綁定服務(wù)器端口,監(jiān)聽端口,在中用一個(gè)函數(shù)就能完成上面?zhèn)€步驟。此時(shí)程序會進(jìn)入睡眠狀態(tài),直到有新的客戶端發(fā)起到服務(wù)器,操作系統(tǒng)會喚醒此進(jìn)程。

概述

想要更好的理解,網(wǎng)絡(luò)編程,寫出一個(gè)高性能的服務(wù),我們需要花點(diǎn)時(shí)間來理解下對于服務(wù)器處理客戶端的整個(gè)流程并且理解一些關(guān)鍵的術(shù)語,本來想在本文中補(bǔ)充一些基礎(chǔ)理論知識,擔(dān)心篇幅過長不利于閱讀,所以以后補(bǔ)發(fā)一些基礎(chǔ)知識,接下來進(jìn)入正題。

理論

主要介紹下實(shí)現(xiàn)一個(gè)網(wǎng)絡(luò)服務(wù)器的基本步驟,代碼會在實(shí)踐環(huán)節(jié)復(fù)現(xiàn)一次。

第一步

我們需要?jiǎng)?chuàng)建一個(gè)socket,綁定服務(wù)器端口(bind),監(jiān)聽端口(listen),在PHP中用stream_socket_server一個(gè)函數(shù)就能完成上面3個(gè)步驟。

第二步

進(jìn)入while循環(huán),阻塞在accept操作上,等待客戶端連接進(jìn)入。此時(shí)程序會進(jìn)入睡眠狀態(tài),直到有新的客戶端發(fā)起connect到服務(wù)器,操作系統(tǒng)會喚醒此進(jìn)程。accept函數(shù)返回客戶端連接的socket

第三步

利用fread讀取客戶端socket當(dāng)中的數(shù)據(jù)收到數(shù)據(jù)后服務(wù)器程序進(jìn)行處理然后使用fwrite向客戶端發(fā)送響應(yīng)。長連接的服務(wù)會持續(xù)與客戶端交互,而短連接服務(wù)一般收到響應(yīng)就會close。

實(shí)踐

在這里我們用代碼來實(shí)現(xiàn)下基本一個(gè)流程,在開始寫代碼之前介紹介幾個(gè)php函數(shù),是我們代碼中可能會用到的,方便大家理解。

函數(shù)

stream_socket_server
stream_socket_accept
call_user_func
is_callable
fread

點(diǎn)擊函數(shù)了解用法
代碼

廢話少說直接開擼~

onConnect = function ($data) {
    echo "新的連接來了", $data, PHP_EOL;
};
//提前注冊了一個(gè)接收消息事件回調(diào)
$worker->onMessage = function ($conn, $message) {
};
$worker->run();

按照之前的流程我們需要監(jiān)聽端口+地址

public function __construct($socket_address) {
         //監(jiān)聽地址+端口
         $this->socket=stream_socket_server($socket_address);
     }

下一步就需要阻塞在accept操作,等待客戶端連接進(jìn)入。此時(shí)程序會進(jìn)入睡眠狀態(tài),直到有新的客戶端發(fā)起connect到服務(wù)器,操作系統(tǒng)會喚醒此進(jìn)程

public function run(){
        while (true) { //循環(huán)監(jiān)聽
         $client = stream_socket_accept($this->socket);//在服務(wù)端阻塞監(jiān)聽
        }
     }

當(dāng)新的連接進(jìn)入喚醒進(jìn)程并且觸發(fā)連接事件回調(diào)

 public function run(){
        while (true) { //循環(huán)監(jiān)聽
         $client = stream_socket_accept($this->socket);//在服務(wù)端阻塞監(jiān)聽
         if(!empty($client) && is_callable($this->onConnect)){//socket連接成功并且是我們的回調(diào)
             //觸發(fā)事件的連接的回調(diào)
             call_user_func($this->onConnect,$client);
         }
        }
     }

這里的連接回調(diào)實(shí)際上觸發(fā)的就是之前準(zhǔn)備好類庫的這里下面這段代碼

$worker->onConnect = function ($data) {
    echo "連接事件:", $data, PHP_EOL;
};

當(dāng)連接成功后利用fread獲取到客戶端的內(nèi)容,并觸發(fā)接收消息事件

     public function run(){
      while (true) { //循環(huán)監(jiān)聽
         $client = stream_socket_accept($this->socket);//在服務(wù)端阻塞監(jiān)聽
         if(!empty($client) && is_callable($this->onConnect)){//socket連接成功并且是我們的回調(diào)
             //觸發(fā)事件的連接的回調(diào)
             call_user_func($this->onConnect,$client);
         }
         //從連接中讀取客戶端內(nèi)容
         $buffer=fread($client,65535);//參數(shù)2:在緩沖區(qū)當(dāng)中讀取的最大字節(jié)數(shù)
         //正常讀取到數(shù)據(jù)。觸發(fā)消息接收事件,進(jìn)行響應(yīng)
         if(!empty($buffer) && is_callable($this->onMessage)){
             //觸發(fā)時(shí)間的消息接收事件
             call_user_func($this->onMessage,$this,$client,$buffer);//傳遞到接收消息事件》當(dāng)前對象、當(dāng)前連接、接收到的消息
         }
       }
     }

到此處基本的一個(gè)網(wǎng)絡(luò)服務(wù)接收基本完成,還需要對請求做出一個(gè)響應(yīng),以HTTP請求為例,這里封裝了一個(gè)http響應(yīng)的方法(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);
     }
 }

當(dāng)觸發(fā)接收消息事件時(shí)對http請求做出響應(yīng)

$worker->onMessage = function ($server,$conn, $message) {
    echo "來自客戶端消息:",$message,PHP_EOL;
    $server->send($conn,"來自服務(wù)端消息");
};

到這就結(jié)束了~,完整代碼直通車

缺點(diǎn)

一次只能處理一個(gè)連接,不支持多個(gè)連接同時(shí)處理

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/30170.html

相關(guān)文章

  • 物聯(lián)網(wǎng)高并發(fā)編程之網(wǎng)絡(luò)編程中線程模型

    摘要:如需了解更多物聯(lián)網(wǎng)網(wǎng)絡(luò)編程知識請點(diǎn)擊物聯(lián)網(wǎng)云端開發(fā)武器庫物聯(lián)網(wǎng)高并發(fā)編程之網(wǎng)絡(luò)編程中的線程模型值得說明的是,具體選擇線程還是進(jìn)程,更多是與平臺及編程語言相關(guān)。 如需了解更多物聯(lián)網(wǎng)網(wǎng)絡(luò)編程知識請點(diǎn)擊:物聯(lián)網(wǎng)云端開發(fā)武器庫 物聯(lián)網(wǎng)高并發(fā)編程之網(wǎng)絡(luò)編程中的線程模型 值得說明的是,具體選擇線程還是進(jìn)程,更多是與平臺及編程語言相關(guān)。例如 C 語言使用線程和進(jìn)程都可以(例如 Nginx 使用進(jìn)程...

    ziwenxie 評論0 收藏0
  • 入門架構(gòu)——機(jī)高性能

    摘要:協(xié)作方式在高并發(fā)場景中,必須要讓服務(wù)器同時(shí)維護(hù)大量請求連接,可能是一個(gè)服務(wù)進(jìn)程創(chuàng)建另一個(gè)進(jìn)程,也可能是一個(gè)服務(wù)線程去創(chuàng)建另一個(gè)線程,但連接結(jié)束后進(jìn)程或線程就銷毀了,這是一個(gè)巨大的浪費(fèi)一個(gè)自然的想法就是通過創(chuàng)建一個(gè)進(jìn)程線程池從而達(dá)到資源復(fù)用, showImg(https://segmentfault.com/img/bVbtgn1?w=313&h=208); 協(xié)作方式 在高并發(fā)場景中,必...

    UCloud 評論0 收藏0
  • nginx、swoole高并發(fā)原理初探

    摘要:一閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應(yīng)結(jié)果發(fā)給相應(yīng)的連接請求處理完成因?yàn)榛冢悦總€(gè)可以處理無數(shù)個(gè)連接請求。如此,就輕松的處理了高并發(fā)。 一、閱前熱身 為了更加形象的說明同步異步、阻塞非阻塞,我們以小明去買奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點(diǎn)在消息通知的方式上...

    denson 評論0 收藏0
  • nginx、swoole高并發(fā)原理初探

    摘要:一閱前熱身為了更加形象的說明同步異步阻塞非阻塞,我們以小明去買奶茶為例。等奶茶做好了,店員喊一聲小明,奶茶好了,然后小明去取奶茶。將響應(yīng)結(jié)果發(fā)給相應(yīng)的連接請求處理完成因?yàn)榛?,所以每個(gè)可以處理無數(shù)個(gè)連接請求。如此,就輕松的處理了高并發(fā)。 一、閱前熱身 為了更加形象的說明同步異步、阻塞非阻塞,我們以小明去買奶茶為例。 1、同步與異步 ①同步與異步的理解 同步與異步的重點(diǎn)在消息通知的方式上...

    617035918 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<