PHP socket 程式設計
阿新 • • 發佈:2020-07-19
1. 什麼是socket
Socket就是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。 在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面, 對使用者來說,一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。Socket 是對TCP/IP協議的封裝,Socket本身並不是協議,而是一個呼叫介面(API),通過Socket,我們才能使用TCP/IP協議。
PS:其實就類似我們自己去實現了一個抽象化的瀏覽器通訊,只不過用的不是http協議,自己組裝資料,傳送資料,繫結埠,監聽埠,獲取資料等等一些網路通訊的功能。
1.1 相關網路協議
TCP/IP(Transmission Control Protocol/Internet Protocol)即傳輸控制協議/網間協議,是一個工業標準的協議集,它是為廣域網(WANs)設計的。
UDP(User Data Protocol,使用者資料報協議)是與TCP相對應的協議。它是屬於TCP/IP協議族中的一種。
HTTP 協議即超文字傳送協議(Hypertext Transfer Protocol ),是Web聯網的基礎,也是手機聯網常用的協議之一,HTTP協議是建立在TCP協議之上的一種應用。
1.2 php中的socket
Socket擴充套件是基於流行的BSD sockets,實現了和socket通訊功能的底層介面,它可以和客戶端一樣當做一個socket伺服器。
2. socket 相關函式
socket_accept() 接收一個socket連線 socket_bind() 把socket繫結在一個IP地址和埠上 socket_clear_error() 清除socket的錯誤或者最後的錯誤程式碼 socket_close() 關閉一個socket資源 socket_connect() 開始一個socket連線 socket_create_listen() 在指定埠開啟一個socket監聽 socket_create_pair() 產生一對沒有區別的socket到一個數組裡 socket_create() 產生一個socket,相當於產生一個socket的資料結構 socket_get_option() 獲取socket選項 socket_getpeername() 獲取遠端類似主機的ip地址 socket_getsockname() 獲取本地socket的ip地址 socket_iovec_add() 新增一個新的向量到一個分散/聚合的陣列 socket_iovec_alloc() 這個函式建立一個能夠傳送接收讀寫的iovec資料結構 socket_iovec_delete() 刪除一個已經分配的iovec socket_iovec_fetch() 返回指定的iovec資源的資料 socket_iovec_free() 釋放一個iovec資源 socket_iovec_set() 設定iovec的資料新值 socket_last_error() 獲取當前socket的最後錯誤程式碼 socket_listen() 監聽由指定socket的所有連線 socket_read() 讀取指定長度的資料 socket_readv() 讀取從分散/聚合陣列過來的資料 socket_recv() 從socket裡結束資料到快取 socket_recvfrom() 接受資料從指定的socket,如果沒有指定則預設當前socket socket_recvmsg() 從iovec裡接受訊息 socket_select() 多路選擇 socket_send() 這個函式傳送資料到已連線的socket socket_sendmsg() 傳送訊息到socket socket_sendto() 傳送訊息到指定地址的socket socket_set_block() 在socket裡設定為塊模式 socket_set_nonblock() socket裡設定為非塊模式 socket_set_option() 設定socket選項 socket_shutdown() 這個函式允許你關閉讀、寫、或者指定的socket socket_strerror() 返回指定錯誤號的詳細錯誤 socket_write() 寫資料到socket快取 socket_writev() 寫資料到分散/聚合陣列
2.1 八大核心函式
socket的關鍵函式1: socket_create($net引數1,$stream引數2,$protocol引數3) 作用:建立一個socket套接字,說白了,就是一個網路資料流。 返回值:一個套接字,或者是false,引數錯誤發出E_WARNING警告 引數1是:網路協議, 網路協議有哪些?它的選擇項就下面這三個: AF_INET: IPv4 網路協議。TCP 和 UDP 都可使用此協議。一般都用這個,你懂的。 AF_INET6: IPv6 網路協議。TCP 和 UDP 都可使用此協議。 AF_UNIX: 本地通訊協議。具有高效能和低成本的 IPC(程序間通訊)。 引數2:套接字流,選項有: SOCK_STREAM SOCK_DGRAM SOCK_SEQPACKET SOCK_RAW SOCK_RDM。 這裡只對前兩個進行解釋: SOCK_STREAM TCP 協議套接字。 SOCK_DGRAM UDP協議套接字。 引數3:protocol協議,選項有: SOL_TCP: TCP 協議。 SOL_UDP: UDP協議。 關鍵函式2: socket_connect($socket引數1,$ip引數2,$port引數3) 作用:連線一個套接字,返回值為true或者false 引數1:socket_create的函式返回值 引數2:ip地址 引數3:埠號 關鍵函式3: socket_bind($socket引數1,$ip引數2,$port引數3) 作用:繫結一個套接字,返回值為true或者false 引數1:socket_create的函式返回值 引數2:ip地址 引數3:埠號 關鍵函式4: socket_listen($socket引數1,$backlog 引數2) 作用:監聽一個套接字,返回值為true或者false 引數1:socket_create的函式返回值 引數2:最大監聽套接字個數 關鍵函式5: socket_accept($socket) 作用:接收套接字的資源資訊,成功返回套接字的資訊資源,失敗為false 引數:socket_create的函式返回值 關鍵函式6: socket_read($socket引數1,$length引數2) 作用:讀取套接字的資源資訊, 返回值:成功把套接字的資源轉化為字串資訊,失敗為false 引數1:socket_create或者socket_accept的函式返回值 引數2:讀取的字串的長度 關鍵函式7: socket_write($socket引數1,$msg引數2,$strlen引數3) 作用:把資料寫入套接字中 返回值:成功返回字串的位元組長度,失敗為false 引數1:socket_create或者socket_accept的函式返回值 引數2:字串 引數3:字串的長度 關鍵函式8: socket_close($socket) 作用:關閉套接字 返回值:成功返回true,失敗為false 引數:socket_create或者socket_accept的函式返回值
1.2 socket 案例
sever.php
<?php /** * Socket服務端 * author: flycorn * email: [email protected] * time: 16/12/27 下午3:43 */ //設定無限請求超時時間 set_time_limit(0); $ip = '127.0.0.1'; $port = 8099; //建立socket if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() 失敗的原因是:".socket_strerror($sock)."\n"; exit(); } //把socket繫結在一個IP地址和埠上 if(($ret = socket_bind($sock,$ip,$port)) < 0) { echo "socket_bind() 失敗的原因是:".socket_strerror($ret)."\n"; exit(); } //監聽由指定socket的所有連線 if(($ret = socket_listen($sock,4)) < 0) { echo "socket_listen() 失敗的原因是:".socket_strerror($ret)."\n"; exit(); } //次數 $count = 0; do{ //接收一個Socket連線 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, 2048); $talkback = "收到的資訊:$buf\n"; echo $talkback; //第5次結束 if(++$count >= 5){ break; } } //關閉socket socket_close($msgsock); }while(true);
client.php (客戶端)
<?php /** * Socket客戶端 * author: flycorn * email: [email protected] * time: 16/12/27 下午4:03 */ error_reporting(E_ALL); //設定無限請求超時時間 set_time_limit(0); echo "<h2>TCP/IP Connection</h2>\n"; $ip = '127.0.0.1'; $port = 8099; //建立socket if(($socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) { echo "socket_create() 失敗的原因是:".socket_strerror($socket)."\n"; exit(); } echo "OK. \n"; echo "試圖連線 '$ip' 埠 '$port'...\n"; //連線socket if(($result = socket_connect($socket, $ip, $port)) < 0){ echo "socket_connect() 失敗的原因是:".socket_strerror($sock)."\n"; exit(); } echo "連線OK\n"; $in .= "hello flycorn\r\n"; $out = ''; //寫資料到socket快取 if(!socket_write($socket, $in, strlen($in))) { echo "socket_write() 失敗的原因是:".socket_strerror($sock)."\n"; exit(); } echo "傳送到伺服器資訊成功!\n"; echo "傳送的內容為:$in \n"; //讀取指定長度的資料 while($out = socket_read($socket, 2048)) { echo "接收伺服器回傳資訊成功!\n"; echo "接收的內容為:",$out; } echo "關閉SOCKET...\n"; socket_close($socket); echo "關閉OK\n";
文章摘錄來源:https://www.jianshu.com/p/f671d3895d13https://www.cnblogs.com/loveyoume/p/6076101.html