1. 程式人生 > 實用技巧 >php socket網路程式設計基礎知識(一):開篇

php socket網路程式設計基礎知識(一):開篇

說明

  • 雖然我們普通的web程式設計中很少用到網路程式設計,但實際上我們一直都在用,例如nginx和php-fpm之間的通訊就是網路通訊,也會發現他們的一些配置引數,其實就是網路程式設計中一些函式的引數。
  • 我們說是通訊,想當然的就是兩臺機器之間的通訊,但實際上同一臺機器上同樣可以通過迴環來通訊互動,就像是nginx和php-fpm既可以部署在同一機器上,也可以負載均衡部署在多機器上。
  • php本身是提供了網路通訊方面的功能的,但相關的文件大都沒有翻譯成中文,而且文件說明和舉例也比較少和抽象,需要有一定基礎的才能看懂,導致更少的人去用了
  • 如果學習這方面的話,只看文件時不行的,需要查詢大量的關聯資料才能理解,查詢資料可以不侷限在php方面,其它語言也都有網路通訊相關,原理都是共通的。
  • 這裡記錄下自己的一些知識點簡單的總結。

相關的需求

我們只有在解決實際問題時,才能真正理解各個方法的用法含義,那我們假設如果要實現類似web端的客服與顧客的聊天,會遇到哪些問題或者應該怎麼解決:

  • 雖然是兩者聊天,但實際上兩者並不是直接聊天,而是通過中間伺服器的中轉,也就是客服---伺服器建立通訊、顧客---伺服器建立通訊,類似傳送信件,需要通過郵局來進行轉發。
  • 這也就要求伺服器至少同時接入兩個客戶端(客戶和顧客),但伺服器怎麼能同時處理兩個呢?目前我們能想到的應該就是用多程序或多執行緒解決了,當一個顧客接入開啟一個程序來處理與顧客的通訊,主程序繼續檢測客服是否有接入,如果客服也接入則同樣開啟程序處理。
  • 然後就單獨客服---伺服器這一個通訊來說,讀和寫會不會衝突呢,客服需要接收訊息,但是我們根本不知道伺服器(顧客)什麼時候傳送訊息,那理所當然的做法是用while迴圈一直檢測服務端傳送的訊息,那這裡就會卡住,都去在迴圈中檢測讀訊息了那我要怎麼傳送訊息呢,目前我們能想到的解決方法還是開新程序或執行緒來解決讀寫衝突的問題。
  • 我們的通訊一般還需要每隔一段時間就傳送一個心跳包,否則如果長時間不通訊的話,系統會關閉此連線。這又出現問題了,我們的程式讀、寫都處理不過來了,心跳要怎麼傳送呢,我們能想到的方法還是開新程序或執行緒來單獨傳送心跳包。
  • 上面說的問題,只想想就頭痛了,程序、執行緒官方文件都介紹的比較少,更不要說還要考慮程序、執行緒他們之間的通訊了,但這確實是一種解決方法。
  • 那單程序就無法處理了嗎?並不是,我們可以用系統提供的select類似的IO多路複用方法,此方法可以通過系統核心來監控接入、讀取、寫入等事件,當發生了事件就會通知你,然後去處理就可以了,這樣在一個程序中就可以完成上述的操作,但一個程序所接收的總量畢竟有限,所以要提高併發時還是會用到多程序來處理,但此時的邏輯會比上方所說的簡單很多,至於心跳包的問題,我們則可以通過定時器訊號來解決,也無需多開一個新程序或執行緒。
  • 這裡還有一個剛開始學習時,我自己非常迷惑的地方,在學習各種示例時,不管是傳送的還是接收的訊息都是寫死的,但是我們實際的需求是需要使用者填寫,那中間如何插入進去呢?這相當於慣性思維,一提到使用者填寫立刻想到post傳輸,然後就有些混亂衝突了,但實際上對於web端聊天場景來說他們之間的傳輸是用的websocket,顧客點擊發送事件中直接呼叫ws.send類似方法傳送訊息,服務端收到訊息觸發讀取訊息事件,在事件中轉發給客服即可。而對於類似app推送訊息的場景來說,後臺填寫資料確實是需要post傳輸到web服務端,然後web服務端接收到post資料後再通過呼叫send類似方法傳送給socket服務端,socket服務端接收到訊息後再向各個socket客戶端廣播訊息,由於php指令碼執行完就關閉了,所以web服務端到socket服務端同樣會關閉,但並沒有什麼影響,每次都重新連線就是了,我們只需要保證socket服務端和客戶端維持長連線就行了,web服務端只有後臺想傳送推送資訊時連線一下socket服務端就行了。
  • 所以我們要實現上方的功能,需要學習的知識點為:
    • Socket基礎
    • Stream流基礎
    • 多程序
    • 訊號
    • IO模型

相關的php功能

  • Socket函式,最基礎的呼叫,用法和純C的非常相似
  • Stream函式,php做的socket呼叫的進一步封裝,比上面呼叫更加方便
  • PCNTL函式 ,socket程式設計一般是離不開多程序及訊號等功能
  • POSIX函式,程序資訊,使用者、組等管理,訊號傳送等
  • Libevent函式,事件驅動庫

相關資料

緣由

原先有專案接觸過與java網路通訊相關的,當時用php沒有搞定,最後還是用他們的java相關sdk做的,所以一直想補充這方面的知識,但是一直都沒有看下去,這次的起因是這樣的:

  • 看python的基礎知識,正好看到pack、協程、select這塊
  • 那php也有相應的pack、yield函式等,對應著看其中的差異(其實對照其它語言更能加深理解)
  • php的yied相關,並沒有進一步封裝,而swoole號稱協程方面處理的很好
  • swoole用C寫的,但自己C功底不好,所以想先看類似的用純php寫的Workerman
  • Workerman很簡潔,寫的也非常好,裡面有些函式自己看不懂,所以就對應著檢視相關的了

關聯

注意

  • 這個前幾篇文章早已寫過,一直存草稿裡,打算全寫完再發出來,但後來由於自己已經轉JAVA開發了,所以後續的章節都沒有寫完,目前是沒有計劃再寫了,可能等學習完JAVA的Netty後會再總結,時隔好久又翻到了存草稿裡的這幾篇文章,還是先發出來供參考吧