本篇文章給大家分享的內容是關於php socket編程常用的函數以及簡單c/s互動的實現,內容很詳細,有需要的朋友可以參考一下,希望可以協助到你們。
Socket 簡介
Socket 的官方解釋:
在網路編程中最常用的方案便是Client/Server(客戶機/伺服器)模型。在這種方案中客戶應用程式向伺服器程式請求服務。一個服務程式通常在一個眾所周知的地址監聽對服務的請求,也就是說,服務進程一 直處於休眠狀態,直到一個客戶向這個服務的地址提出了串連請求。在這個時刻,服務程式被"驚醒"並且為客戶提供服務-對客戶的請求作出適當的反應。為了方便這種Client/Server模型的網路編程,90年代初,由Microsoft聯合了其他幾家公司共同制定了一套WINDOWS下的網路編程介面,即WindowsSockets規範,它不是一種網路通訊協定,而是一套開放的、支援多種協議的Windows下的網路編程介面。現在的Winsock已經基本上實現了與協議無關,你可以使用Winsock來調用多種協議的功能,但較常使用的是TCP/IP協議。Socket實際在電腦中提供了一個通訊連接埠,可以通過這個連接埠與任何一個具有Socket介面的電腦通訊。應用程式在網路上傳輸,接收的資訊都通過這個Socket介面來實現
我們可以簡單的把 Socket 理解為一個可以連通網路上不同電腦應用程式之間的管道,把一堆資料從管道的 A 端扔進去,則會從管道的 B 端(同時還可以從C、D、E、F……端冒出來)。
注意
:我們會在不同語境下使用不同的詞語去修飾 socket,你只需要對它有個概念就好了,因為 socket 本身就沒有真正意義上的實體
Socket 函數介紹
Socket 通訊依次會進行 Socket 建立、 Socket 綁定、Socket 監聽、Socket 收發、Socket 關閉幾個階段,下面我們列舉出 PHP 網路編程中最常用也是必不可少的幾個常用的函數進行進一步的說明。
socket_create
TODO : 建立一個新的 socket 資源
函數原型: resource socket_create ( int $domain , int $type , int $protocol )
它包含三個參數,分別如下:
domain:AF_INET、AF_INET6、AF_UNIX,AF
的釋義就 address family
,地址族的意思,我們常用的有 ipv4、ipv6
type: SOCK_STREAM、SOCK_DGRAM等,最常用的就是SOCK_STREAM
,基於位元組流的SOCKET類型,也是TCP協議使用的類型
protocol: SOL_TCP、SOL_UDP 這個就是具體使用的傳輸協議,一般可靠的傳輸我們選擇 TCP,遊戲資料轉送我們一般選用 UDP 協議
socket_bind
TODO : 將建立的 socket 資源綁定到具體的 ip 地址和連接埠
函數原型: bool socket_bind ( resource $socket , string $address [, int $port = 0 ] )
它包含三個參數,分別如下:
socket_listen
TODO : 在具體的地址下監聽 socket 資源的收發操作
函數原型: bool socket_listen ( resource $socket [, int $backlog = 0 ] )
它包含兩個個參數,分別如下:
socket_accept
TODO : 監聽之後,接收一個即將來臨的新的串連,如果串連建立成功,將返回一個新的 socket 控制代碼(你可以理解為子進程,通常父進程用來接收新的串連,子進程負責具體的通訊)
函數原型: resource socket_accept ( resource $socket )
socket_write
TODO : 將指定的資料發送到 對應的 socket 管道
函數原型: int socket_write ( resource $socket , string $buffer [, int $length ] )
socket_read
TODO : 擷取傳送的資料
函數原型: int socket_read ( resource $socket , int $length )
socket_close
TODO : 關閉 socket 資源
函數原型: void socket_close ( resource $socket )
stream_socket_server
由於建立一個SOCKET的流程總是 socket、bind、listen,所以PHP提供了一個非常方便的函數一次性建立、綁定連接埠、監聽連接埠
函數原型: resource stream_socket_server ( string $local_socket [, int &$errno [, string &$errstr [, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN [, resource $context ]]]] )
socket 實現 C/S 互動
基於上面的函數我們可以很方便的去構建 socket 通訊程式(在這裡我希望讀者能單獨建立一個目錄比如socket
因為後續我們還會建立很多檔案)我們先編輯一個服務端程式 server.php
,如下:
<?phpdate_default_timezone_set("Asia/Shanghai");error_reporting(E_NOTICE );/* 確保在串連用戶端時不會逾時 */set_time_limit(0);$ip = '127.0.0.1';$port = 8090;/* +------------------------------- * @socket通訊整個過程 +------------------------------- * @socket_create * @socket_bind * @socket_listen * @socket_accept * @socket_read * @socket_write * @socket_close +-------------------------------- *//*---------------- 以下操作都是手冊上的 -------------------*/if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() Why failure is:".socket_strerror($sock)."\n";}if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() Why failure is:".socket_strerror($ret)."\n";}if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() Why failure is:".socket_strerror($ret)."\n";}echo "Start time:".date('Y-m-d H:i:s') . PHP_EOL;echo "Listening at ".$ip.':'.$port.PHP_EOL;do { /* 建立新的串連 */ if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { # 串連成功輸出 Socket id $i = (int)$msgsock; echo "welcome client $i"; # 向用戶端通訊(反饋) $msg ="串連成功!\n"; socket_write($msgsock, $msg, strlen($msg)); } socket_close($msgsock);} while (true);socket_close($sock);?>
再編輯一個用戶端程式client.php
,如下:
<?phpset_time_limit(0);$port = 8090;$ip = "127.0.0.1";/* +------------------------------- * 用戶端 socket 串連整個過程 +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- *//** * @socket_connect:用戶端發起通訊端串連 * @param socket resource $socket 建立的$socket資源 * @param address string SOCK_STREAM IP地址|Unix通訊端 * @param port int 連接埠 *//** * @socket_create:建立並返回一個通訊端 * @param domain string AF_INET IPV4 網路通訊協定 * @param type string SOCK_STREAM 全雙工系統位元組流(可用的通訊端類型) * @param protocol string SOL_TCP 具體協議(IPV4下的TCP協議) * @param return 通訊端 */$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";}else { echo "try to connect '$ip' port: '$port'...\n";}$result = socket_connect($socket, $ip, $port); #socket_connect的傳回值應該是boolean值if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";}else { # 串連成功輸出提示資訊 echo "connect successfully\n"; # 向服務端發送資料 socket_write($socket, " hello ", 1024); # 擷取服務端資料 $result = socket_read($socket, 1024); echo "伺服器回傳資料為:" . $result; echo "CLOSE SOCKET...\n"; socket_close($socket); echo "CLOSE OK\n"; }?>
然後我們開啟終端(命令列)進入檔案目錄下依次執行:
php server.phpphp client.php
運行效果如下:
注意
伺服器監聽時進程是掛起的不能進行其他動作,你可能需要另起一個終端執行用戶端程式