來源:不言 發(fā)布時(shí)間:2018-12-13 15:29:36 閱讀量:1042
本篇文章給大家?guī)淼膬?nèi)容是關(guān)于PHPSocket編程中多進(jìn)程的回聲服務(wù)器的詳細(xì)介紹(圖文) ,有一定的參考價(jià)值,有需要的朋友可以參考一下,希望對你有所幫助。
上次的回聲服務(wù)程序有個(gè)很大的缺點(diǎn),就是只能同時(shí)連接一個(gè)客戶端,這明顯是不合理的。
所以這次采用多進(jìn)程的方式來實(shí)現(xiàn)同時(shí)為多個(gè)客戶端提供服務(wù)。
以下是最終的效果:
(通過 ps 命令可以查看到我們創(chuàng)建的工作進(jìn)程)
(通過 xshell 打開多個(gè)終端,并向服務(wù)程序連接多個(gè)客戶端)
在開始編碼之前,先介紹一下什么是進(jìn)程。
進(jìn)程,即正在運(yùn)行的占用內(nèi)存的程序,是一個(gè)獨(dú)立的內(nèi)存空間。比如我們在 windows 上打開記事本軟件,這個(gè)操作就相當(dāng)于打開了一個(gè)進(jìn)程。
而多進(jìn)程則是通過創(chuàng)建多個(gè)進(jìn)程來共同完成一件事。
我們本次只需實(shí)現(xiàn)服務(wù)端的程序就行了,客戶端還使用之前的。沒讀過之前文章的可以查看歷史文章。
在PHP中,我們可以使用 pcntl_fork 函數(shù)來實(shí)現(xiàn)創(chuàng)建進(jìn)程。
下面是函數(shù)的原型:
1 |
|
官方解釋:
成功時(shí),在父進(jìn)程執(zhí)行線程內(nèi)返回產(chǎn)生的子進(jìn)程的PID,在子進(jìn)程執(zhí)行線程內(nèi)返回0。失敗時(shí),在 父進(jìn)程上下文返回-1,不會(huì)創(chuàng)建子進(jìn)程,并且會(huì)引發(fā)一個(gè)PHP錯(cuò)誤。
為什么說是父進(jìn)程執(zhí)行的線程呢,因?yàn)橐粋€(gè)進(jìn)程中至少包含一個(gè)線程 ,而這個(gè)線程則是進(jìn)程的主線程。
父進(jìn)程在調(diào)用 pcntl_fork 時(shí),同時(shí)復(fù)制出一個(gè)獨(dú)立的子進(jìn)程,這個(gè)子進(jìn)程具有父進(jìn)程同樣的上下文。也就是說兩個(gè)進(jìn)程共享一個(gè)代碼而已。
下面進(jìn)入編碼環(huán)節(jié):
通過執(zhí)行 pcntl_fork 函數(shù),同時(shí)復(fù)制了一個(gè)子進(jìn)程,此時(shí),如果上下文是父進(jìn)程的執(zhí)行環(huán)境,則返回值為子進(jìn)程的進(jìn)程號(hào)。如果是子進(jìn)程的執(zhí)行環(huán)境,則返回0。所以下面的if程序結(jié)構(gòu),兩個(gè)分支都執(zhí)行了。
子進(jìn)程同樣還是以前的邏輯,用來接收客戶端的消息,同時(shí)發(fā)送給客戶端。
倒數(shù)第二行調(diào)用了 pcntl_waitpid 函數(shù),在講解這個(gè)函數(shù)之前我們先了解一下什么是僵尸進(jìn)程。
正常情況下,子進(jìn)程是通過父進(jìn)程創(chuàng)建的。由于進(jìn)程是互相獨(dú)立的內(nèi)存結(jié)構(gòu),所以父進(jìn)程是不會(huì)知道子進(jìn)程的運(yùn)行狀態(tài)的。子進(jìn)程完成自己的任務(wù)之后,并不能自己退出,這個(gè)時(shí)候需要父進(jìn)程通過操作系統(tǒng)來取得子進(jìn)程的狀態(tài),從而回收子進(jìn)程。否則,我們的子進(jìn)程將會(huì)成為一個(gè)垃圾資源,也就是僵尸進(jìn)程。
下面是這個(gè)函數(shù)的函數(shù)原型:
1 |
|
官方解釋:
等待或返回fork的子進(jìn)程狀態(tài)。
其實(shí)上面的代碼是有問題的,在 foreach 中第一次調(diào)用 pcntl_waitpid 之后 ,主進(jìn)程其實(shí)此時(shí)是被阻塞著,一直在等待第一個(gè)子進(jìn)程退出,而其他的子進(jìn)程若此時(shí)異常退出,則并沒有被主進(jìn)程回收,也就產(chǎn)生了僵尸進(jìn)程。而在實(shí)際的開發(fā)中主進(jìn)程還是要做其他的事情的。
所以這里推薦采用非阻塞的方式,很簡單,只需加上第三個(gè)參數(shù):WNOHANG。即:pcntl_waitpid ($pid, $status, WNOHANG)
這樣子可以在沒有子進(jìn)程退出的情況下立刻返回,從而繼續(xù)執(zhí)行后續(xù)代碼。
相關(guān)推薦:
服務(wù)器端PHP多進(jìn)程編程實(shí)戰(zhàn)
服務(wù)器端PHP多進(jìn)程編程實(shí)戰(zhàn)_PHP教程