上一篇文章是對socket編程的入門,此次咱們基於socket實現一個簡單的收發消息的服務。php
實現思路:linux
先說服務端:編程
客戶端:後端
因爲PHP沒有原生的從命令行接收用戶輸入的函數,因此這裏經過如下方式來實現:socket
'/dev/stdin',這個是linux的標準輸入,其實這個函數就是把linux的標準輸入,重定向到咱們的後端PHP程序了。而後咱們的PHP程序就接收到了用戶的輸入,接着就能夠把這個輸入發送到回聲服務程序的服務端了。函數
經過上面一篇文章,咱們已經對於建立套接字的流程有了必定的瞭解,在這裏就很少說這些了。spa
接下來開始服務端的實現:命令行
echo_server.php:server
代碼解讀:圖片
第1處:這裏直接使用了上一篇文章介紹的stream_socket_server函數,能夠一次性的完成socket的建立、綁定以及監聽。
第2處:開始監聽咱們建立的套接字(至於這裏爲何加上@,由於stream_socket_accept函數若是必定時間內沒有收到客戶端的鏈接的話,會報一個warning)
第3處:經過fread函數,讀取輸入緩衝區,一次讀取1024個字節
第4處:將讀取到的字符寫入輸入緩衝,從而發送到客戶端。
經過上面的程序咱們已經實現了回聲服務程序的服務端。
接下來咱們能夠運行一下,會發現咱們的echo_server.php已經進入阻塞狀態,等待客戶端鏈接。
接着實現客戶端:
echo_client.php
代碼解讀:
第1處:調用咱們的重定向標準輸入函數,調用此函數以後,若是不輸入任何字符,程序是不會執行到下一行的,由於這裏會被阻塞。
第2處:若是咱們輸入了q這個字符,將跳出while循環,緊接着會執行fclose,關閉鏈接。這裏要注意一下,客戶端關閉鏈接以後,會向服務端發送一個信號,告訴服務端我已經斷開鏈接了,服務端接受到以後將關閉此客戶端的鏈接。
第3處:將讀取到的輸入信息寫入緩衝區,從而發送到服務端。
第4處到第5處是要重點講解的內容。
此處爲何不直接經過fread函數一次性讀取服務端返回的消息呢?
如下是對於這個問題的解答:
對於每個socket,都有一個發送緩衝區和接收緩衝區。若是咱們發送的數據足夠大,則可能分爲兩次發送。也就是說fwrite以後,咱們發送的字符有可能被分紅兩部分發送了,而服務端的代碼是在不斷的接收數據,而後返回數據。
因此客戶端可能出現以下狀況:發送一次字符以後,客戶端還沒有接收到所有的數據就調用了fread函數,從而打印屢次。
因此對於這個問題最好的解決方法就是,咱們客戶端是可以提早知道要接收的字符大小的,因此這裏經過strlen函數獲取要接收的數據大小,若是不足這個大小則繼續讀取,直到知足條件以後再輸出。
下面是程序運行的效果:
以上則是咱們的回聲服務程序,記得本身動手練習哦,眼過千遍不如手過一遍!
本人會持續分享一些關於編程以及編程自學相關的文章,記錄本身的自學編程之路。同時但願本身的分享可以幫助一些對編程感興趣以及正在編程道路上的朋友。歡迎你們關注個人公衆號「阿毛的Coding之路 」。