簡單理解php的socket編程

来源:http://www.cnblogs.com/loveyoume/archive/2016/11/19/6076101.html
-Advertisement-
Play Games

php的socket編程算是比較難以理解的東西吧,不過,我們只要理解socket幾個函數之間的關係,以及它們所扮演的角色,那麼理解起來應該不是很難了,在筆者看來,socket編程,其實就是建立一個網路服務的客戶端和服務端,這和mysql的客戶端和服務端是一樣的,你只要理解mysql的客戶端和服務端是 ...


    phpsocket編程算是比較難以理解的東西吧,不過,我們只要理解socket幾個函數之間的關係,以及它們所扮演的角色,那麼理解起來應該不是很難了,在筆者看來,socket編程,其實就是建立一個網路服務的客戶端和服務端,這和mysql的客戶端和服務端是一樣的,你只要理解mysql的客戶端和服務端是怎麼一回事,你就應該能夠理解下麵我要講的東西吧。

    關於socket編程所涉及到的網路協議,什麼TCP啊,UDP啊,什麼socket三次握手等等,這些網路協議網上有很詳細的解釋,這裡不講,只截個socket建立套接的過程圖讓你瞧瞧:

                  

 

    這個圖是我辛辛苦苦從別人那裡盜截過來的,你一定要好好看啊,同時,在這裡我也向那個被我盜截圖的筆者表示感謝,本人對自己盜取你的圖案表示歉意,還望你大人大量不要計較啊。本人實在太懶了,懶得畫圖,(其實是對自己的畫圖技術表示不自信,呵呵)。

    socket是怎麼建立連接的呢?上面已經提到過了,它建立連接的過程是與mysql的客戶端和服務端的連接本質是一樣的。而它與mysql不同的是,mysql的服務端和客戶端都已經為我們編輯好了,我們只要應用就行了。但是,關鍵時刻來啦,socket它什麼東西都沒有提供給我們,唯一提供給我們的就是:幾十個socket函數。

    這言外之意就是說,socket編程就是要我們自己創建服務端和客戶端,也就是說,``socket編程``——就是要我們自己建立一個類似於mysql的服務端和客戶端的應用。

    說到這裡,我想問一句,你說這socket讓人頭疼不?它既不建立個服務端,也不建立個客戶端給我們應用,非要讓我們自己去應用socket的函數,創建一個屬於我們自己的網路協議套接應用,這是不是很讓你頭疼呢?頭疼也沒辦法,要是你需要自己的應用,你還是不得不跟socket打交道。呵呵,這隻是題外話,不多說,下麵進入正題。

    在你沒有被socket編程搞蒙之前,我還是讓你看看socket的幾個關鍵函數,先給你解釋一下它們各自的作用。不然,要是對socket編程一點基礎都沒有的人看到了,我怕你看了之後,就果斷跳過這篇文章,從此對socket產生恐懼症了。呵呵,又多說了。

    socket的關鍵函數1

      socket_create($net參數1$stream參數2$protocol參數3)

    作用:創建一個socket套接,說白了,就是一個網路數據流

    返回值:一個套接字,或者是false,參數錯誤發出E_WARNING警告

    php的線上手冊那裡說得更清楚:

    socket_create創建並返回一個套接字,也稱作一個通訊節點。一個典型的網路連接由 2 個套接字構成,一個運行在客戶端,另一個運行在伺服器端。

上面一句話是從php線上手冊那裡複製過來的。看到沒有,這裡說得意思是不是和我上面反反覆復提到的客戶端與服務端一模一樣?呵呵。

    參數1是:網路協議,

    網路協議有哪些?它的選擇項就下麵這三個:

    AF_INET:     IPv4 網路協議。TCP UDP 都可使用此協議。一般都用這個,你懂的。

    AF_INET6:   IPv6 網路協議。TCP UDP 都可使用此協議。

    AF_UNIX:      本地通訊協議。具有高性能和低成本的 IPC(進程間通訊)。

    參數2:套接字流,選項有:

    SOCK_STREAM  SOCK_DGRAM  SOCK_SEQPACKET  SOCK_RAW  SOCK_RDM

    這裡只對前兩個進行解釋:

    SOCK_STREAM  TCP 協議套接字。

    SOCK_DGRAM   UDP協議套接字。

    欲瞭解更多請鏈接這裡:http://php.net/manual/zh/function.socket-create.php

    參數3protocol協議,選項有:

    SOL_TCP:  TCP 協議。

    SOL_UDP:  UDP協議。

    從這裡可以看出,其實socket_create函數的第二個參數和第三個參數是相關聯的。

    比如,假如你第一個參數應用IPv4協議:AF_INET,然後,第二個參數應用的是TCP套接字:SOCK_STREAM

    那麼第三個參數必須要用SOL_TCP這個應該不難理解。

    TCP 協議套接字嘛,當然只能用TCP協議了,是不是?如果你應用UDP套接字,那麼第三個參數該怎麼選擇我就不說了,呵呵,你懂的。

 

    關鍵函數2

    socket_connect($socket參數1,$ip參數2,$port參數3)

    作用:連接一個套接字,返回值為true或者false

    參數1socket_create的函數返回值

    參數2ip地址

    參數3:埠號

 

    關鍵函數3

    socket_bind($socket參數1,$ip參數2,$port參數3)

    作用:綁定一個套接字,返回值為true或者false

       參數1socket_create的函數返回值

    參數2ip地址

    參數3:埠號

 

    關鍵函數4

    socket_listen($socket參數1,$backlog 參數2)

    作用:監聽一個套接字,返回值為true或者false

    參數1socket_create的函數返回值

    參數2最大監聽套接字個數

 

    關鍵函數5

    socket_accept($socket)

    作用:接收套接字的資源信息,成功返回套接字的信息資源,失敗為false

        參數:socket_create的函數返回值

 

    關鍵函數6

    socket_read($socket)

    作用:讀取套接字的資源信息,

    返回值:成功把套接字的資源轉化為字元串信息,失敗為false

      參數:socket_create或者socket_accept的函數返回值

 

    關鍵函數7

    socket_write($socket參數1$msg參數2$strlen參數3)

    作用:把數據寫入套接字中

    返回值:成功返回字元串的位元組長度,失敗為false

      參數:socket_create或者socket_accept的函數返回值

 

    關鍵函數8

    socket_close($socket)

    作用:關閉套接字

    返回值:成功返回true,失敗為false

        參數:socket_create或者socket_accept的函數返回值

 

    這八個函數是socket的核心函數,下麵列舉兩個個比較重要的函數

    socket_last_error($socket),參數為socket_create的返回值,作用是獲取套接字的最後一條錯誤碼號,返回值套接字code

    socket_strerror($code),參數為socket_last_error函數的返回值,獲取code的字元串信息,返回值也就是套接字的錯誤信息

    這兩個函數在socket編程中還是很重要的,在寫socket編程的時候,我覺得你還是得利用起來,特別是新手,可以當做調試用

    

    下麵就是代碼了,註意註意,請認真看我的註釋,註釋很重要,註釋很重要,註釋很重要,重要的事情要大喊三遍,呵呵。

    服務端腳本,D:\vhost\test\socket\server_socket.php 

<?php
//創建服務端的socket套接流,net協議為IPv4,protocol協議為TCP
$socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);

    /*綁定接收的套接流主機和埠,與客戶端相對應*/
    if(socket_bind($socket,'127.0.0.1',8888) == false){
        echo 'server bind fail:'.socket_strerror(socket_last_error());
        /*這裡的127.0.0.1是在本地主機測試,你如果有多臺電腦,可以寫IP地址*/
    }
    //監聽套接流
    if(socket_listen($socket,4)==false){
        echo 'server listen fail:'.socket_strerror(socket_last_error());
    }
//讓伺服器無限獲取客戶端傳過來的信息
do{
    /*接收客戶端傳過來的信息*/
    $accept_resource = socket_accept($socket);
    /*socket_accept的作用就是接受socket_bind()所綁定的主機發過來的套接流*/

    if($accept_resource !== false){
        /*讀取客戶端傳過來的資源,並轉化為字元串*/
        $string = socket_read($accept_resource,1024);
        /*socket_read的作用就是讀出socket_accept()的資源並把它轉化為字元串*/

        echo 'server receive is :'.$string.PHP_EOL;//PHP_EOL為php的換行預定義常量
        if($string != false){
            $return_client = 'server receive is : '.$string.PHP_EOL;
            /*向socket_accept的套接流寫入信息,也就是回饋信息給socket_bind()所綁定的主機客戶端*/
            socket_write($accept_resource,$return_client,strlen($return_client));
            /*socket_write的作用是向socket_create的套接流寫入信息,或者向socket_accept的套接流寫入信息*/
        }else{
            echo 'socket_read is fail';
        }
    /*socket_close的作用是關閉socket_create()或者socket_accept()所建立的套接流*/
        socket_close($accept_resource);
    }
}while(true);
socket_close($socket);

 

    客戶端腳本,D:\vhost\test\socket\client_socket.php

 

<?php
    //創建一個socket套接流
    $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
    /****************設置socket連接選項,這兩個步驟你可以省略*************/
     //接收套接流的最大超時時間1秒,後面是微秒單位超時時間,設置為零,表示不管它
    socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 0));
     //發送套接流的最大超時時間為6秒
    socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 6, "usec" => 0));
    /****************設置socket連接選項,這兩個步驟你可以省略*************/

    //連接服務端的套接流,這一步就是使客戶端與伺服器端的套接流建立聯繫
    if(socket_connect($socket,'127.0.0.1',8888) == false){
        echo 'connect fail massege:'.socket_strerror(socket_last_error());
    }else{
        $message = 'l love you 我愛你 socket';
        //轉為GBK編碼,處理亂碼問題,這要看你的編碼情況而定,每個人的編碼都不同
        $message = mb_convert_encoding($message,'GBK','UTF-8');
        //向服務端寫入字元串信息

        if(socket_write($socket,$message,strlen($message)) == false){
            echo 'fail to write'.socket_strerror(socket_last_error());

        }else{
            echo 'client write success'.PHP_EOL;
            //讀取服務端返回來的套接流信息
            while($callback = socket_read($socket,1024)){
                echo 'server return message is:'.PHP_EOL.$callback;
            }
        }
    }
    socket_close($socket);//工作完畢,關閉套接流

 

     怎麼測試這兩個腳本呢?

    首先打開windows的dos視窗,就是cmd黑視窗,然後,運行php D:\vhost\test\socket\server_socket.php,

    讓服務端的的黑視窗持續運行的,

    其次,php的客戶端腳本可以通過瀏覽器運行,也可以再開一個cmd黑視窗運行

    php D:\vhost\test\socket\client_socket.php

      在這裡請註意:php這個運行命名必須加入windows的環境變數中,假如不知道怎麼加,

    請進入php運行命令目錄用絕對命令運行,也可以百度把php命令加入環境變數中

    這裡是我的情況,你的文件地址可能和我不一樣,請按照你的地址情況來操作,否則,後果自負,呵呵

    上面已經說過了,socket編程必須要有服務端才能交流,所以服務端的黑視窗是必須讓它持續開著的。

 

    後記補充:

socket_set_option($socket參數1 $level 參數2$optname 參數3$optval 參數4)

這個函數的作用是給套接字設置數據流選項,還是一個很重要的函數。

參數1socket_create或者socket_accept的函數返回值

參數2SOL_SOCKET,好像只有這個選項

參數3與參數4是相關聯的,

參數3可為:SO_REUSEADDR  SO_RCVTIMEO     S0_SNDTIMEO

解釋一下:

SO_REUSEADDR  是讓套接字埠釋放後立即就可以被再次使用

        參數3假如是這個,則參數4可以為true或者false

SO_RCVTIMEO   是套接字的接收資源的最大超時時間

SO_SNDTIMEO   是套接字的發送資源的最大超時時間

  參數3假如是這兩個,則參數4是一個這樣的數組array('sec'=>1,'usec'=>500000)

  數組裡面都是設置超時的最大時間,不過,一個是秒為單位,一個是微秒單位,作用都一樣

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 使用 async & await 一步步將同步代碼轉換為非同步編程 【博主】反骨仔 【出處】http://www.cnblogs.com/liqingwen/p/6079707.html 序 上次,博主通過《利用 async & await 的非同步編程》一文介紹了 async & await 的基本用 ...
  • 前言 開發授權服務框架一般使用OAuth2.0授權框架,而開發Webapi的授權更應該使用OAuth2.0授權標準,OAuth2.0授權框架文檔說明參考:https://tools.ietf.org/html/rfc6749 .NET Core開發OAuth2的項目需要使用IdentityServe ...
  • 在本機跑過10000萬個併發連接,用的jmeter,jmeter占用了1.4G左右的記憶體、90%多的CPU,我也不知道為什麼這麼耗資源,筆記本勉強還能工作。 現在模擬的是15個客戶端,100毫秒發送一次數據,效果如下: ...
  • .NET Core配置文件 在以前.NET中配置文件都是以App.config / Web.config等XML格式的配置文件,而.NET Core中建議使用以JSON為格式的配置文件,因為使用起來更加方面靈活,而且可以使用.NET Core中的DI註入配置數據。 使用: 配置文件appsettin ...
  • RSA: 獲取RSA實例: 獲取公鑰: 獲取私鑰: ...
  • Json.NET: 獲取類實例對應的jtoken:JObject.FromObject() 獲取數組實例對應的jtoken:JArray.FromObject() ...
  • Nhibernate 4.0 教程 目錄 1. 下載Nhibernate 4.04. 1 2. 入門教程... 2 3. 測試項目詳解... 3 4. 總結... 7 附:關聯知識點... 7 知識點1:C#靜態構造函數... 7 知識點2:關於Visual Studio文件生成操作... 8 前言 ...
  • 繼承的特點:繼承父類的屬性和方法。單繼承(多層繼承)c++里的繼承是多繼承 特性 :方法的覆寫(重寫) java中的繼承和OC中一樣。 比如:人可以養狗; 人 >狗 :整體和部分(擁有)關係。 球隊 >球員 :整體和部分的關係。 代碼中是最常見 has a 的關係 人 >學生 :學生是人 : 說明有 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...