說明
- 雖然我們普通的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函式,事件驅動庫
相關資料
- PHP多行程初探系列文章,寫的非常不錯
- Workerman,純php寫的socket通訊的封裝,我們可以查看其原始碼來了解各個socket相關函式具體是怎么用的,
- workerman原始碼解讀,這位同學分析的挺全面的,
- Python 中的 Socket 編程(指南),即便沒學過python,但是理解socket的功能后看關鍵字也能理解大部分內容,
緣由
原先有專案接觸過與java網路通信相關的,當時用php沒有搞定,最后還是用他們的java相關sdk做的,所以一直想補充這方面的知識,但是一直都沒有看下去,這次的起因是這樣的:
- 看python的基礎知識,正好看到pack、協程、select這塊
- 那php也有相應的pack、yield函式等,對應著看其中的差異(其實對照其它語言更能加深理解)
- php的yied相關,并沒有進一步封裝,而swoole號稱協程方面處理的很好
- swoole用C寫的,但自己C功底不好,所以想先看類似的用純php寫的Workerman
- Workerman很簡潔,寫的也非常好,里面有些函式自己看不懂,所以就對應著查看相關的了
關聯
- php socket網路編程基礎知識(二):socket函式
- php socket網路編程基礎知識(三):stream函式
- php socket網路編程基礎知識(四):多行程
- php socket網路編程基礎知識(五):信號(未完成)
- php socket網路編程基礎知識(六):IO模型(未完成)
- php socket網路編程基礎知識(七):libevent(未完成)
注意
- 這個前幾篇文章早已寫過,一直存草稿里,打算全寫完再發出來,但后來由于自己已經轉JAVA開發了,所以后續的章節都沒有寫完,目前是沒有計劃再寫了,可能等學習完JAVA的
Netty后會再總結,時隔好久又翻到了存草稿里的這幾篇文章,還是先發出來供參考吧
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/5058.html
標籤:PHP
