在實際開發中,如果想要建立基於socket的應用程式,就需要詳細瞭解socket的操作方法,要是像瞭解並熟練使用這些操作方法,就需要先瞭解php中的各種socket函數。在上一章節中我們詳細介紹了php中的socket是什嗎?這裡就介紹一下php中的socket函數。socket函數在php中有幾十個之多,這裡列舉一些主要的socket函數來介紹一下。
它們的文法格式參數如下:
1. socket_create
socket_create ( int $domain , int $type , int $protocol )
此函數用於建立一個socket,它有三個參數,傳回值是一個控制代碼(資源)。
$domain 指定建立socket時使用的通訊協定族,其可選的值為:
AF_INET: 基於IPv4的Internet協議
AF_INET6:基於IPv6的Internet協議
AF_UNIX:UNIX本地通訊協定
$type 指定socket通訊的互動類型,其可選的值為:
SOCK_STREAM:提供序列化的、可靠的、全雙工系統的、基於串連的位元組流傳輸,支援TCP
SOCK_DGRAM:提供資料報式的、不需連線的、固定最大長度的、自動定址功能的傳輸,支援UDP
SOCK_SEQPACKET:提供序列化的、可靠的、雙通道的、基於串連的資料報傳輸
SOCK_RAW:提供原始的網路訪問協議,可手工構建特殊協議類型的通訊端,支援ICMP請求(如 ping)
SOCK_RDM:提供可靠的資料報傳輸,無法保證順序
$protocol 指定socket使用哪種具體的傳輸協議,包括ICMP、UDP、TCP,常量SOL_UDP對應UDP,常量SOL_TCP對應常量TCP。
2. socket_bind
socket_bind ( resource $socket , string $address [, int $port = 0 ] )
此函數用於將IP地址和連接埠綁定到socket_create建立的控制代碼中,有三個參數,返回布爾值。
$socket 是必選參數,代表socket_create函數建立的控制代碼
$address 是必選參數,代表要綁定的IP地址
$port 是選擇性參數,代表要綁定的連接埠號碼,指定哪個連接埠用來監聽socket串連,當socket_create函數的第一個參數為AF_INET時,需要指定這個參數。
3. socket_listen
socket_listen ( resource $socket [, int $backlog = 0 ] )
該函數用於監聽即將接入的socket串連,僅當socket的互動類型為SOCK_STREAM或SOCK_SEQPACKET時可
用,它有兩個參數,返回布爾值。
$socket 是必選參數,代表socket_create函數建立的控制代碼(且已綁定了主機)
$backlog 是選擇性參數,表示隊列中等候處理的(允許積壓的)最大串連數。
4. socket_set_block
socket_set_block ( resource $socket )
該函數用於將socket控制代碼設定為阻塞模式,只有一個必選參數,返回布爾值。它可以將非阻塞模式的socket轉換為阻塞模式。
當在一個阻塞模式的socket中執行某種操作(receive、send、connect、accept等)時,指令碼將暫停執行,直到它收到一個訊號或它完成了該操作。
$socket 是必選參數,代表一個有效socket控制代碼(被socket_create或socket_accept建立的)。
說明一下阻塞模式和非阻塞模式的區別:
非阻塞是指函數操作在不能立刻得到結果之前,不會阻塞當前的線程,而會立即返回。而阻塞是指幹不完就不準回來,必須得到對方的回應後才能繼續下一步操作。特別是當使用者比較多時,設定成非阻塞是很必要的。如果是阻塞模式,若兩個用戶端同時串連上,伺服器端在處理一個用戶端請求時,另外一個用戶端的請求就會被阻塞,只有等到前一個用戶端的事情處理完了之後,後一個用戶端的請求才會被響應。
5. socket_write
socket_write ( resource $socket , string $buffer [, int $length = 0 ] )
該函數用於向socket中寫入指定大小的緩衝資料,有三個參數,返回寫入的資料的位元組數。
$socket 是必選參數,代表一個有效socket控制代碼。
$buffer 是必選參數,指定要寫入的字串資料。
$length 是選擇性參數,指定輪流寫入socket中的資料的位元組數,如果它的值大於$buffer的位元組數,它會靜默地截取至$buffer的位元組數長度。
6. socket_read
socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )
該函數用於從socket中讀取指定位元組長度的資料,有三個參數,返回讀取的字串資料。
$socket 是必選參數,代表一個有效socket控制代碼。
$length 是必選參數,指定讀取的位元組長度。
$type 是選擇性參數,預設值為PHP_BINARY_READ,即安全讀取位元據;另一個可選的值為PHP_NORMAL_READ,表示當遇到 \r 或 \n 時,停止讀取。
7. pfsockopen
pfsockopen ( string $hostname [, int $port = -1 [, int &$errno [, string &$errstr [, float $timeout = ini_get("default_socket_timeout") ]]]] )
該函數用於實現一個持久的socket串連,即長串連,返回一個控制代碼。它與 fsockopen 的區別在於,pfsockopen 建立的串連,在指令碼執行完畢後,並不會斷開。
8. socket_set_option
socket_set_option ( resource$socket , int$level , int$optname , mixed$optval )
該函數用於設定socket的控制選項,有四個參數,返回布爾值。
$socket 是必選參數,代表一個有效socket控制代碼。
$level 是必選參數,指定option起作用的協議層級,一般取常量 SOL_SOCKET。
$optname 是必選參數,指定要控制的選項名稱。
$optval 是必選參數,指定選項的值。
9. socket_last_error
socket_last_error ([ resource$socket ] )
該函數用於擷取任何socket函數產生的最後錯誤代號,傳回值為整型。
10. socket_strerror
socket_strerror ( int $errno )
該函數用於擷取錯誤代號代表的錯誤描述,傳回值為字串。
以上所有的函數都是PHP中關於socket的,使用這些函數,你必須把你的socket開啟,如果你沒有開啟,請編輯你的php.ini檔案,去掉下面這行前面的注釋:
extension=php_sockets.dll
如果你不知道你的socket是否開啟,那麼你可以使用phpinfo()函數來確定socket是否開啟。
下面通過建立一個服務端和用戶端的例子來說明這些函數的用法:
伺服器端
<?php//確保在串連用戶端時不會逾時set_time_limit(0);$ip = '127.0.0.1';$port = 1935;/* +------------------------------- * @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() 失敗的原因是:".socket_strerror($sock)."\n";}if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() 失敗的原因是:".socket_strerror($ret)."\n";}if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() 失敗的原因是:".socket_strerror($ret)."\n";}$count = 0;do { if (($msgsock = socket_accept($sock)) < 0) { echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n"; break; } else { //發到用戶端 $msg ="測試成功!\n"; socket_write($msgsock, $msg, strlen($msg)); echo "測試成功了啊\n"; $buf = socket_read($msgsock,8192); $talkback = "收到的資訊:$buf\n"; echo $talkback; if(++$count >= 5){ break; }; } //echo $buf; socket_close($msgsock);} while (true);socket_close($sock);?>
2. 用戶端
<?phperror_reporting(E_ALL);set_time_limit(0);echo "<h2>TCP/IP Connection</h2>\n";$port = 1935;$ip = "127.0.0.1";/* +------------------------------- * @socket串連整個過程 +------------------------------- * @socket_create * @socket_connect * @socket_write * @socket_read * @socket_close +-------------------------------- */$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);if ($socket < 0) { echo "socket_create() failed: reason: " . socket_strerror($socket) . "\n";}else { echo "OK.\n";}echo "試圖串連 '$ip' 連接埠 '$port'...\n";$result = socket_connect($socket, $ip, $port);if ($result < 0) { echo "socket_connect() failed.\nReason: ($result) " . socket_strerror($result) . "\n";}else { echo "串連OK\n";}$in = "Ho\r\n";$in .= "first blood\r\n";$out = '';if(!socket_write($socket, $in, strlen($in))) { echo "socket_write() failed: reason: " . socket_strerror($socket) . "\n";}else { echo "發送到伺服器資訊成功!\n"; echo "發送的內容為:<font color='red'>$in</font> <br>";}while($out = socket_read($socket, 8192)) { echo "接收伺服器回傳資訊成功!\n"; echo "接受的內容為:",$out;}echo "關閉SOCKET...\n";socket_close($socket);echo "關閉OK\n";?>
【相關教程推薦】
1. 《php.cn獨孤九賤(4)-php視頻教程》
2. php編程從入門到精通全套教程