您好,登錄后才能下訂單哦!
這篇文章主要介紹“PHP+Socket如何實現客戶端與服務端數據傳輸”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“PHP+Socket如何實現客戶端與服務端數據傳輸”文章能幫助大家解決問題。
socket介紹
實現網絡進程之間的通信,幾乎所有應用程序都是采用 socket,socket 是應用層與 TCP/IP 協議族通信的中間抽象層,它是一組接口。在設計模式中,socket 其實是一個門面模式,它把復雜的 TCP/IP 協議族隱藏在 socket 接口后面,對用戶來說,一組簡單的接口就是全部,讓 socket 去組織數據,以符合指定的協議
socket 的英文原意是 「孔」或「插座」,通常也被稱作「套接字」,用于描述 IP 地址和端口,是一個通信鏈的句柄,可以用來實現不同虛擬機或不同計算機之間的通信。
socket 鏈接的三個過程
服務端監聽:IP+端口號
客戶端請求:發出向服務端的 IP 以及端口的連接請求
鏈接確認:服務端套接字監聽到或者說接收到客戶端套接字連接請求,他就會建立一個新的進程,把服務端的套接字描述發給客戶端,以響應客戶端的請求,一旦客戶端確認了此描述,連接就建立好了。兒服務端的套接字繼續處于監聽狀態,繼續接受其他客戶端套接字的連接請求。
如果需要在 php 中使用 socket,則需要在編譯 php 是添加 --enable-sockets
配置項來啟用,可使用 php -m|grep sockets
命令檢查啟用情況
快速體驗
服務端與客戶端簡略代碼如下,運行后服務端會阻塞等待客戶端連接,客戶端會在控制臺要求輸入內容,輸入后信息會在服務端打印,同時客戶端顯示轉為大寫的內容,此示例服務端與客戶端運行在一臺服務器:
服務端監聽
<?php
// 創建套接字
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// 設置 ip 被釋放后立即可使用
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, true);
// 綁定ip與端口
socket_bind($socket, 0, 8888);
// 開始監聽
socket_listen($socket);
while (true) {
// 接收內容
$conn_sock = socket_accept($socket);
socket_getpeername($conn_sock, $ip, $port);
// echo '請求ip: ' . $ip . PHP_EOL . '端口: ' . $port;
while (true) {
// 獲取消息內容
$msg = socket_read($conn_sock, 10240);
// TODO 處理業務邏輯
// 將信息轉為大寫并原樣返回客戶端
socket_write($conn_sock, strtoupper($msg));
echo $msg;
}
}
客戶端連接
<?php
// 創建套接字
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
// 連接服務端
socket_connect($socket, '127.0.0.1', 8888);
while (true) {
// 讓控制臺輸入內容
fwrite(STDOUT, '請輸入內容:');
$in = fgets(STDIN);
// 向服務端發送內容
socket_write($socket, $in);
// 讀取服務端發送的消息
$msg = socket_read($socket, 10240);
echo $msg;
}
語法解釋
socket_create
socket_create(int $domain,int $type, int $protocol): resource|false
創建并返回一個套接字資源,通常也稱作一個通訊節點。一個典型的 socket 由至少 2 個套接字組成,其中一個運行在客戶端,一個運行在服務端。
參數:
domain
指定當前套接字使用什么協議,可用協議如下:
Domain | 描述 |
---|---|
AF_INET | IPv4 網絡協議,TCP 與 UDP 都可使用此協議 |
AF_INET6 | IPv6 網絡協議,TCP 與 UDP 都可使用此協議 |
AF_UNIX | 本地通訊協議,具有高性能與低成本的 IPC |
type
用戶指定當前套接字使用的類型
type | 描述 |
---|---|
SOCK_STREAM | 可順序化的、可靠的、全雙工的、基于鏈接的字節流,支持數據傳送流量控制機制。TCP 協議基于這種流式套接字。 |
SOCK_DGRAM | 數據報文的支持(無連接、不可靠、固定最大長度)UDP 協議基于這種報文套接字 |
SOCK_SEQPACKET | 可順序化的、可靠的、全雙工的、面向連接的、固定最大長度的數據通信,數據端通過接收每一個數據段來讀取整個數據包 |
SOCK_RAW | 讀取原始的網絡協議,這種特殊的套接字可用于手工構建任意類型的協議,一般使用這個套接字來實現 ICMP 請求 |
SOCK_RDM | 可靠的數據層,但不保證到達順序,一般的操作系統都未實現此功能 |
protocol
設置指定 domain 套接字下的具體協議,如果所需協議是 TCP 或者 UDP,可以直接使用常量 SOL_TCP
或 SOL_UDP
,這個參數的具體值可通過 getprotobyname()
函數獲取
返回值
socket_create()
正確時返回一個套接字資源,失敗時返回 false
。可以調用 socket_last_error()
獲取錯誤碼,錯誤碼可以通過 socket_strerror(int $err_no)
轉換為文字的錯誤說明。
socket_bind
socket_bind(resource $socket, string $address [, int $port]): bool
綁定一個地址與端口到套接字
參數:
socket
使用 socket_create()
創建的套接字資源
address
如果套接字是 AF_INET
族,那么 address
必須是一個四點法的 IP 地址,例如 127.0.0.1
、0.0.0.0
如果套接字是 AF_UNIX
族,那么 address
是 Unix 套接字一部分(例如 /tmp/my.sock
)
port
(可選)
該參數僅用于使用 AF_INET
族時,指定當前套接字監聽的端口號
返回值:
綁定成功返回 true
,失敗時則返回 false
,同 socket_create
,在綁定失敗時可以調用 socket_last_error()
獲取錯誤碼,錯誤碼可以通過 socket_strerror(int $err_no)
轉換為文字的錯誤說明。
socket_listen
socket_listen(resource $socket [, int $backlog]): bool
在使用 socket_create()
創建套接字并使用 socket_bind()
將其綁定到名稱之后,可能會告訴它偵聽套接字上的傳入連接。該函數僅適用于 SOCK_STREAM
或 SOCK_SEQPACKET
類型的套接字。
參數:
socket
使用 socket_create()
創建的套接字資源
backlog
最大數量的積壓傳入連接將排隊等待處理,如果連接請求到達時隊列已滿,則客戶端可能會收到指示為 ECONNREFUSED
的錯誤。或者,如果底層協議支持重傳,則可能會忽略該請求,以便重試可能會成功。
返回值:
綁定成功返回 true
,失敗時則返回 false
,可以調用 socket_last_error()
獲取錯誤碼,錯誤碼可以通過 socket_strerror(int $err_no)
轉換為文字的錯誤說明。
socket_accept
socket_accept(resource $socket): resource|false
當有新的客戶端連接時,返回一個新的 socket 資源以用于與客戶端通信,如有多個連接排隊,則返回第一個連接,相反如果沒有待處理的連接,該函數會默認阻塞當前進程,直至新的客戶端連接、斷開
參數:
socket
使用 socket_create()
創建的套接字資源
返回值:
成功時返回一個新的套接字資源,錯誤時返回 false
,可以調用 socket_last_error()
獲取錯誤碼,錯誤碼可以通過 socket_strerror(int $err_no)
轉換為文字的錯誤說明。
socket_connect
socket_connect(resource $socket, string $address [, int $port = null]): bool
使用套接字實例發起到 address
的連接
參數:
socket
該參數必須是由 socket_create()
創建的 socket
實例
address
如果套接字是 AF_INET
族,那么 address
必須是一個四點法的 IP 地址,例如 127.0.0.1
如果支持 IPv6 并且套接字是 AF_INET6
,那么 address
也可以是一個有效的 IPv6 地址(例如 ::1
)
如果套接字是 AF_UNIX
族,那么 address
是 Unix 套接字一部分(例如 /tmp/my.sock
)
返回值:
成功時返回 true
, 或者在失敗時返回 false
socket_write
socket_write(resource $socket, string $data [, int $length = null]): int|false
傳輸數據至指定套接字
參數:
socket
使用 socket_create()
或 socket_accept()
創建的套接字資源
data
要發送的內容
length
(可選)
可以指定發送套接字的替代字節長度。如果這個長度大于實際發送內容的長度,它將被靜默地截斷為實際發送內容的長度。
返回值:
成功時返回成功發送的字節數,或者在失敗時返回 false
,可以調用 socket_last_error()
與 socket_strerror(int $err_no)
獲取具體錯誤信息
socket_read
socket_read(resource $socket, int $length, int $mode = PHP_BINARY_READ): string|false
從套接字資源內讀取數據
參數:
socket
使用 socket_create()
或 socket_accept()
創建的套接字資源(服務端為 socket_accept()
客戶端為 socket_create()
)
length
指定最大能夠讀取的字節數。否則您可以使用 \r
、\n
、\0
結束讀取(根據 mode
參數設置)
mode
(可選)
PHP_BINARY_READ
(默認)- 使用系統的 recv()
函數。二進制安全地讀取數據。
PHP_NORMAL_READ
- 讀取到 \n
、\r
時停止。
返回值:
socket_read()
返回一個字符串,表示接收到的數據。如果發生了錯誤(包括遠程主機關閉了連接),則返回 false
,可以調用 socket_last_error()
與 socket_strerror(int $err_no)
獲取具體錯誤信息
socket_close
socket_close(resource $socket): void
關閉并銷毀一個套接字資源
參數:
socket
使用 socket_create()
或 socket_accept()
創建的套接字資源
返回值:
無
關于“PHP+Socket如何實現客戶端與服務端數據傳輸”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。