摘要:而之所以只打出一個和,是因為默認是阻塞的。那么本篇就介紹了經典網絡模型阻塞模型,里面也涉及到了蠻多的知識點,比較有意思,但是也提到了該模型效率較低,所以下一篇開始我會介紹效率更高的復用的網絡模型,敬請期待。
前面我們實現了一個簡單的 C/S 交互,接下來我們自然要介紹和學習一下常見的網絡交互模型
Accept 阻塞模型是一種相對古老的模型,不過里面蘊含了許多有趣的知識,比如阻塞/非阻塞、鎖、超時重傳...
服務端程序 acceptSever.php" . $ct_data . PHP_EOL; fwrite($conn, "Received $ct_size byte data./r/n"); fclose($conn); } fclose($socket); } } new SocketServer(2000);客戶端程序 acceptClient.php
代碼解析首先,解釋一下以上的代碼邏輯:客戶端 acceptClient.php 循環發送數據,最后發送結束符;服務端 accept Server.php 使用 accept 阻塞方式接收 socket 連接,然后循環接收數據,直到收到結束符,返回結果數據(接收到的字節數)客戶端收到服務器返回的數據,寫入日志。雖然邏輯很簡單,但是其中有幾種情況很值得分析一下:
A> 默認情況下,運行 php socket_client.php test,客戶端打出 10 個 W,服務端打出若干個 R 后面是接收到的數據,socket.log 記錄下服務端返回的接收結果數據,效果如下:
這種情況很容易理解,不再贅述。然后,使用 telnet 命令同時打開多個客戶端,你會發現服務器一個時間只處理一個客戶端,如圖所示:
其他需要在后面“排隊”;這就是阻塞 IO 的特點,這種模式的弱點很明顯,效率極低。B> 只打開 socket_client.php 第 29 行的注釋代碼,再次運行 php socket_client.php test 客戶端打出一個 W,服務端也打出一個 R,之后兩個程序都卡住了。這是為什么呢,分析邏輯后你會發現,這是由于客戶端在未發送結束符之前就向服務端要返回數據;而服務端由于未收到結束符,也在向客戶端要結束符,造成死鎖。而之所以只打出一個 W 和 R,是因為 fread 默認是阻塞的。要解決這個死鎖,必須打開 socket_client.php 第 17 行的注釋代碼,給 socket 設置一個 0.1 秒的超時,再次運行你會發現隔 0.1 秒出現一個 W 和 R 之后正常結束,服務端返回的接收結果數據也正常記錄了。可見 fread 缺省是阻塞的,我們在編程的時候要特別注意,如果沒有設置超時,就很容易會出現死鎖。
C> 只打開 14 行注釋設置腳本為非阻塞,運行 php socket_client.php test,結果基本和情況 A 相同,唯一不同的是 socket.log 沒有記錄下返回數據,這是因為當我們非阻塞下客戶端不必等待接收到服務器的響應結果就可以繼續往下執行,當執行到 debug 的時候,讀取的數據還是空的,所以 socket.log 也是空的。這里可以看出客戶端運行在阻塞和非阻塞模式的區別,當然在客戶端不在乎接受結果的情況下,可以使用非阻塞模式來獲得最大效率。
D> 運行 php socket_client.php 是連續運行 10 次上面的邏輯,這個沒什么問題;但是很奇怪的是如果你使用 39 - 45 行的代碼,用 popen 同時開啟 10 個進程來運行,就會造成服務器端的死循環,十分怪異!后來經調查發現只要是用 popen 打開的進程創建的連接會導致 fread 或者 socket_read 出錯直接返回空字串,從而導致死循環,查閱 PHP 源代碼后發現 PHP 的 popen 和 fread 函數已經完全不是 C 原生的了,里面都插入了大量的 php_stream_* 實現邏輯,初步估計是其中的某個 bug 導致的 Socket 連接中斷所導致的,解決方法就是打開 socket_server.php 中 33 行的代碼,如果連接中斷則跳出循環,但是這樣一來就會有很多數據丟失了,這個問題需要特別注意!
Accept 阻塞模型 結語本來想著寫一篇關于 socket 網絡編程 和 網絡交互模型的過渡篇—— 進程篇的,但是篇幅不是很多獨立成篇有點雞肋,所以打算把它放到后面——番外篇。那么本篇就介紹了 經典網絡模型——Accept 阻塞模型,里面也涉及到了蠻多的知識點,比較有意思,但是也提到了該模型效率較低,所以下一篇開始我會介紹 效率更高的I/O復用的網絡模型,敬請期待。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/29130.html
摘要:這跟國內文化學習路徑編程意識都有關系,當然還有一個重要原因就是沒有比較詳盡的資料無從下手,那么通過這系列文章我希望小白能夠走近網絡編程。 我們應該要明白一點:但凡涉及網絡的事務,一定要經過網絡的各個層次,PHP程序員可能更多地是在服務端的應用層打交道很少接觸應用層下面的傳輸層、網絡層。這跟國內 PHP文化、學習路徑、編程意識都有關系,當然還有一個重要原因就是沒有比較詳盡的資料無從下手,...
摘要:在這個時刻,服務程序被驚醒并且為客戶提供服務對客戶的請求作出適當的反應。為了方便這種模型的網絡編程,年代初,由聯合了其他幾家公司共同制定了一套下的網絡編程接口,即規范,它不是一種網絡協議而是一套開放的支持多種協議的下的網絡編程接口。 這篇文章將會介紹一下 Socket 編程中相關的 PHP 函數,并簡單實現一個 C/S 的交互 Socket 簡介 Socket 的官方解釋:在網絡編程中...
摘要:如果你想體驗原味編程,用開頭的比較適合否則建議使用流函數。有關流的知識,請參考本人之前的博文回顧之流。接下來我們用流函數實現一個簡單的客戶端和服務端。流函數中的和兩個函數是我們想要的。本文目的是簡要介紹中的編程,行文到此已經達到目的。 轉載請注明文章出處: https://tlanyan.me/php-review... PHP回顧系列目錄 PHP基礎 web請求 cookie w...
摘要:下文如無特殊聲明將使用進程同時表示進程線程。收到數據后服務器程序進行處理然后使用向客戶端發送響應。現在各種高并發異步的服務器程序都是基于實現的,比如。 并發 IO 問題一直是服務器端編程中的技術難題,從最早的同步阻塞直接 Fork 進程,到 Worker 進程池/線程池,到現在的異步IO、協程。PHP 程序員因為有強大的 LAMP 框架,對這類底層方面的知識知之甚少,本文目的就是詳細介...
閱讀 2703·2021-11-25 09:43
閱讀 2085·2021-11-24 09:39
閱讀 1954·2021-11-17 09:33
閱讀 2750·2021-09-27 14:11
閱讀 1840·2019-08-30 15:54
閱讀 3224·2019-08-26 18:27
閱讀 1264·2019-08-23 18:00
閱讀 1810·2019-08-23 17:53