這篇文章給大家分享的內容是關於php socket程式設計常用的函數以及簡單c/s互動的實現,內容很詳細,有需要的朋友可以參考一下,希望可以幫助到你們。
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 關閉幾個階段,下面我們列舉出PHP 網路程式設計中最常使用也是必不可少的幾個常用的函數進行進一步的說明。
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 協定
TODO : 將建立的socket 資源綁定到特定的ip 位址和連接埠
函數原型: bool socket_bind ( resource $socket , string $ address [, int $port = 0 ] )
它包含三個參數,分別如下:
socket: 使用socket_create
建立的socket 資源,可以認為是socket 對應的id
#address: ip 位址
函數原型:
bool socket_listen ( resource $socket [ , int $backlog = 0 ] )
創建的socket資源
resource socket_accept ( resource $socket )
建立的socket資源
TODO : 將指定的資料傳送到對應的socket 管道
函數原型: int socket_write ( resource $socket , string $buffer [, int $length ] )
socket: 使用socket_create
建立的socket資源
buffer: 寫入到socket
資源中的資料
length: 控制寫入到socket
資源中的buffer
的長度,如果長度大於buffer
的容量,則取buffer
的容量
TODO : 取得傳送的資料
函數原型: int socket_read ( resource $socket , int $length )
socket: 使用socket_create
建立的socket資源
length: socket
資源中的buffer
的長度
TODO: 關掉socket 資源
函數原型: void socket_close ( resource $socket )
socket: socket_accept
或socket_create
產生的資源,不能用於stream
資源的關閉
由於創建一個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 ]]]]
函數建立的資源流上下文
因為後續我們還會建立很多檔案)我們先編輯一個服務端程式server.php
,如下:<pre class="brush:php;toolbar:false"><?php date_default_timezone_set("Asia/Shanghai");
error_reporting(E_NOTICE );
/* 确保在连接客户端时不会超时 */
set_time_limit(0);
$ip = &#39;127.0.0.1&#39;;
$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(&#39;Y-m-d H:i:s&#39;) . PHP_EOL;
echo "Listening at ".$ip.&#39;:&#39;.$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);
?></pre>
再編輯一個客戶端程式
,如下:<pre class="brush:php;toolbar:false"><?php set_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 &#39;$ip&#39; port: &#39;$port&#39;...\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";
}
?></pre>
然後我們打開終端機(命令列)進入檔案目錄下依序執行:
php server.php php client.php
運行效果如下:
注意
伺服器監聽時進程是掛起的不能進行其他操作,你可能需要另起一個終端執行客戶端程式相關推薦:
thinkphp5使用workerman計時器定時爬取網站內容的程式碼
以上是php socket程式設計常用的函數以及簡單c/s互動的實現的詳細內容。更多資訊請關注PHP中文網其他相關文章!