溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

PHP 下 Socket 編程的應(yīng)用

發(fā)布時(shí)間:2021-06-18 15:45:02 來源:億速云 閱讀:177 作者:chen 欄目:編程語(yǔ)言

這篇文章主要介紹“PHP 下 Socket 編程的應(yīng)用”,在日常操作中,相信很多人在PHP 下 Socket 編程的應(yīng)用問題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”PHP 下 Socket 編程的應(yīng)用”的疑惑有所幫助!接下來,請(qǐng)跟著小編一起來學(xué)習(xí)吧!

Socket 并不是一個(gè)協(xié)議, 其本質(zhì)是對(duì) TCP/IP 協(xié)議進(jìn)行的封裝, 并對(duì)外提供了一組接口, 允許用戶可以自由的按相關(guān)協(xié)議組裝數(shù)據(jù), 與服務(wù)器進(jìn)行交互. 一切基于 TCP/IP 的協(xié)議可以通過 Socket 進(jìn)行實(shí)現(xiàn).

PHP 通過 Socket 擴(kuò)展也可以實(shí)現(xiàn)對(duì) Socket 編程. 使用 PHP 進(jìn)行 Socket 通信的簡(jiǎn)單過程如下:

PHP 下 Socket 編程的應(yīng)用

PHP Socket 編程涉及的主要函數(shù):

socket_create(): 初始化一個(gè)socket資源
socket_bind(): 將socket資源綁定到指定地址
socket_listen(): 監(jiān)聽socket的連接請(qǐng)求
socket_accept(): 接受來自客戶端的連接, 返回一個(gè)新socket資源用于通訊. 如果接收到多個(gè)連接, 只會(huì)使用第一個(gè)連接. 沒有連接時(shí), 該函數(shù)保持堵塞狀態(tài), 直到有新的連接. 如果使用socket_set_blocking() or socket_set_nonblock()將socket設(shè)置為非堵塞狀態(tài), 沒有連接時(shí)該函數(shù)返回FALSE
socket_read(): 從連接資源中讀取指定字節(jié)數(shù)的數(shù)據(jù), 讀取成功時(shí), 返回字符串. 失敗時(shí), 返回FALSE. 沒有數(shù)據(jù)時(shí), 返回空字符串
socket_write(): 向連接資源寫入信息返回給客戶端
socket_strerror(): 根據(jù)錯(cuò)誤號(hào)獲取錯(cuò)誤消息
socket_last_error(): 返回上一次錯(cuò)誤的錯(cuò)誤號(hào)

示例一: 客戶端和服務(wù)端的一對(duì)一通信, 由客戶端推送數(shù)據(jù)到服務(wù)端

client.php

$host = '127.0.0.1';
$port = 65533;
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
exit('初始化socket資源錯(cuò)誤: ' . socket_strerror(socket_last_error($sock)));
}
 
if(socket_connect($sock, $host, $port) === FALSE)
{
exit('連接socket失敗: ' . socket_strerror(socket_last_error($sock)));
}
 
$msg = '客戶端1消息';
if(socket_write($sock, $msg) === FALSE)
{
exit('發(fā)送數(shù)據(jù)失敗: ' . socket_strerror(socket_last_error($sock)));
}
 
$data = '';
// 循環(huán)讀取指定長(zhǎng)度的服務(wù)器響應(yīng)數(shù)據(jù)
while($response = socket_read($sock, 4))
{
$data .= $response;
}
echo $data . PHP_EOL;
 
socket_close($sock);

server.php

set_time_limit(0);
 
$ip = '127.0.0.1';
$port = '65533';
$count = 1;
// socket_create(): 初始化一個(gè)socket資源
// socket_strerror(): 根據(jù)錯(cuò)誤號(hào)獲取錯(cuò)誤消息
// socket_last_error(): 返回上一次錯(cuò)誤的錯(cuò)誤號(hào)
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
echo '初始化socket失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_bind(): 將socket資源綁定到指定地址
if(!socket_bind($sock, $ip, $port))
{
echo '綁定端口失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_listen(): 監(jiān)聽socket的連接請(qǐng)求
if(!socket_listen($sock))
{
echo '監(jiān)聽端口: ' . socket_strerror(socket_last_error($sock));
die;
}
 
while(1)
{
// socket_accept(): 接受來自客戶端的連接, 返回一個(gè)新socket資源用于通訊. 如果接收到多個(gè)連接, 只會(huì)使用第一個(gè)連接. 沒有連接時(shí), 該函數(shù)保持堵塞狀態(tài), 直到有新的連接. 如果使用socket_set_blocking() or socket_set_nonblock()將socket設(shè)置為非堵塞狀態(tài), 沒有連接時(shí)該函數(shù)返回FALSE
;
if(($client = socket_accept($sock)) === FALSE)
{
echo '接收連接失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_read(): 從連接資源中讀取指定字節(jié)數(shù)的數(shù)據(jù), 讀取成功時(shí), 返回字符串. 失敗時(shí), 返回FALSE. 沒有數(shù)據(jù)時(shí), 返回空字符串
$content = socket_read($client, 1024);
if($content !== FALSE)
{
echo '消息' . $count . ': ' . $content . PHP_EOL;
$count++;
$response = '接收信息成功!';
// socket_write(): 向連接資源寫入信息返回給客戶端
socket_write($client, $response);
socket_close($client);
}else
{
exit('讀取數(shù)據(jù)錯(cuò)誤: ' . socket_strerror(socket_last_error($client)));
}
}
 
socket_close($sock);

首先在命令行下啟動(dòng) server.php, 然后啟動(dòng) client.php.

服務(wù)消息提示:

PHP 下 Socket 編程的應(yīng)用

客戶端接收的響應(yīng)消息提示

PHP 下 Socket 編程的應(yīng)用

客戶端接收到服務(wù)端的響應(yīng)消息后將斷開連接, 而服務(wù)端會(huì)一直掛起, 等待下一次的連接.

示例二: 客戶端和服務(wù)端的一對(duì)一通信, 由服務(wù)端推送數(shù)據(jù)到客戶端

client.php

// 服務(wù)端地址
$host = '127.0.0.1';
$port = 65533;
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
exit('初始化socket資源錯(cuò)誤: ' . socket_strerror(socket_last_error($sock)));
}
 
if(socket_connect($sock, $host, $port) === FALSE)
{
exit('連接socket失敗: ' . socket_strerror(socket_last_error($sock)));
}
 
$data = '';
// 循環(huán)讀取指定長(zhǎng)度的服務(wù)器響應(yīng)數(shù)據(jù)
while($response = socket_read($sock, 4))
{
$data .= $response;
}
socket_write($sock, '接收消息成功');
echo $data . PHP_EOL;
 
socket_close($sock);

server.php

set_time_limit(0);
 
$ip = '127.0.0.1';
$port = '65533';
// socket_create(): 初始化一個(gè)socket資源
// socket_strerror(): 根據(jù)錯(cuò)誤號(hào)獲取錯(cuò)誤消息
// socket_last_error(): 返回上一次錯(cuò)誤的錯(cuò)誤號(hào)
if(($sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE)
{
echo '初始化socket失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_bind(): 將socket資源綁定到指定地址
if(!socket_bind($sock, $ip, $port))
{
echo '綁定端口失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// socket_listen(): 監(jiān)聽socket的連接請(qǐng)求
if(!socket_listen($sock))
{
echo '監(jiān)聽端口: ' . socket_strerror(socket_last_error($sock));
die;
}
 
// 建立死循環(huán),循環(huán)接收客戶端的連接請(qǐng)求,持續(xù)向連接上的客戶端推送消息
while(1)
{
// socket_accept(): 接受來自客戶端的連接, 返回一個(gè)新socket資源用于通訊. 如果接收到多個(gè)連接, 只會(huì)使用第一個(gè)連接. 沒有連接時(shí), 該函數(shù)保持堵塞狀態(tài), 直到有新的連接. 如果使用socket_set_blocking() or socket_set_nonblock()將socket設(shè)置為非堵塞狀態(tài), 沒有連接時(shí)該函數(shù)返回FALSE
;
if(($client = socket_accept($sock)) === FALSE)
{
echo '接收連接失敗: ' . socket_strerror(socket_last_error($sock));
die;
}
$data = '服務(wù)端消息: ' . date('Y-m-d H:i:s', time());
socket_write($client, $data);
socket_close($client);
}
 
socket_close($sock);

首先通過命令行啟動(dòng) server.php, 此時(shí)服務(wù)端將掛起, 持續(xù)監(jiān)聽指定端口. 然后啟動(dòng) client.php, 客戶端發(fā)起連接, 連接成功后, 將接收到服務(wù)端推送的數(shù)據(jù).

客戶單響應(yīng)提示:

PHP 下 Socket 編程的應(yīng)用

到此,關(guān)于“PHP 下 Socket 編程的應(yīng)用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

php
AI