PHP網(wǎng)絡(luò)編程-- 建立socket通信
這是一篇我在做PHP Web開發(fā)時,發(fā)表于2020年9月15日某平臺的學(xué)習(xí)隨記,關(guān)于如何使用PHP語言建立一個簡單的socket通信,現(xiàn)轉(zhuǎn)載至B站。

Socket編程
Socket函數(shù)
PHP提供了兩種API,一種內(nèi)置在PHP內(nèi)核中,作為主動連接而無法實現(xiàn)端口監(jiān)聽相關(guān)功能;另一種是外部PECL擴展庫,支持監(jiān)聽和交互模式。
內(nèi)置Socket函數(shù)
包括fsockopen和pfsockopen。
fsockopen()其功能是初始化一個socket套接字并連接到目標主機(hosthome)。
pfsockopen()是實現(xiàn)持久化連接,也被稱為長連接。
兩者唯一的區(qū)別就是建立長連接,即客戶端與服務(wù)器端建立連接后不再斷開,完成報文的發(fā)送與接收后再斷開。
兩者執(zhí)行后都會返回一個資源編號,可以使用所有文件操作函數(shù)對其進行操作,
fsockopen負責(zé)創(chuàng)建socket連接,fwrite負責(zé)發(fā)送數(shù)據(jù),fread負責(zé)接收數(shù)據(jù),類似于從文件流中讀/寫。
上面是基于TCP協(xié)議的socket連接,而要創(chuàng)建UDP socket連接,則需要:
該流包裝器內(nèi)可以換為tcp://,可以概括為通用的語法來概括socket地址:
PECL socket 函數(shù)庫
使用如下方法安裝Socket擴展,
該擴展庫有這些函數(shù)。
1. socket_create
Protocol協(xié)議值和說明
AF_INET 大多數(shù)適用,適用TCP或UDP傳輸,使用IPv4地址。
AF_INET6 使用IPv6地址。
AF_UNIX 較少使用,用于Unix和Linux系統(tǒng),一般為客戶端和服務(wù)器在同一臺的情況下使用。
Socket通信類型
SOCK_STREAM 按照順序的、可靠的、數(shù)據(jù)完整的、基于字節(jié)流的連接。使用最多,適用于TCP傳輸
SOCK_DGRAM 無連接的、固定長度的傳輸調(diào)用。不可靠,使用UDP進行連接。
SOCK_SEQPACKET 雙線路的、可靠的連接,發(fā)送固定長度的數(shù)據(jù)包進行傳輸,必須把這個包完整地接受才能進行讀取。
SOCK_RAW 提供單一網(wǎng)絡(luò)訪問,使用ICMP公共協(xié)議。
SOCK_RDM 很少使用。
Socket處理協(xié)議類型
ICMP 互聯(lián)網(wǎng)控制消息協(xié)議,主要使用在網(wǎng)關(guān)和主機上,用來檢查網(wǎng)絡(luò)狀況和報告錯誤信息。
UDP 用戶數(shù)據(jù)報文協(xié)議,無連接、不可靠的傳輸協(xié)議。
TCP 傳輸控制協(xié)議,使用最多、可靠的公共協(xié)議,能保證數(shù)據(jù)包到達接受者那里,如果在傳輸過程中錯誤,那么它將重新發(fā)送出錯數(shù)據(jù)包。
2. socket_bind
用于將IP和端口綁定在socket_create所創(chuàng)建的資源中。
注意,在address中,如果套接字是AF_INET,那么address必須是一個四點分法 的IPv4地址(例如127.0.0.1);如果套接字是AF_UNIX,那么address是Unix/Linux套接字的一部分(例如/tmp/my.sock)。
參數(shù)prot僅僅用于AF_INET套接字連接的時候,并且指定連接中需要監(jiān)聽的端口號。
3. socket_listen
在綁定Socket后,服務(wù)器端使用此函數(shù)監(jiān)聽客戶端數(shù)據(jù)。
backlog是可選項,表示允許的最大連接數(shù)。
4. socket_set_block
設(shè)置為非阻塞模式。
當設(shè)置為非阻塞模式后,會立即返回。與其對應(yīng)的就是阻塞模式,也就是沒有完成任務(wù)不能返回,直到對方有反饋才繼續(xù)下一步處理。
當用戶連接較多時,非阻塞模式是必要的。
5. socket_write
此函數(shù)只是向socket資源寫數(shù)據(jù),并沒有執(zhí)行發(fā)送操作。
6. socket_send
發(fā)送數(shù)據(jù)。
7. socket_read
從socket中讀取指定長度的數(shù)據(jù)。
第三個參數(shù)指的是要讀區(qū)數(shù)據(jù)的類型,默認PHP_BINARY_READ,也就是安全讀取二進制數(shù)據(jù);另一個值可以是PHP_NORMAL_READ,當讀取到“\r”“\n”換行符時停止。
8. ?socket_set_option
此函數(shù)用來設(shè)置socket的控制選項。
bool socket_set_option(resource $socket, int $optname, mixed $optval);
例如,用該函數(shù)設(shè)置發(fā)送超時時間為2s,接收超時時間為3s。
9. socket_last_error
其返回任何socket操作中的函數(shù)生成的最后錯誤信息,其返回值為一個整型值的錯誤代號。
它能夠幫助我們在處理錯誤時找到原因。
建立TCP Socket客戶端
客戶端是通信的發(fā)起者,而服務(wù)器程序負責(zé)被動等待客戶端發(fā)起通信,并對其做出響應(yīng)。
1. 連接TCP服務(wù)器
使用socket_connect函數(shù)。
當運行此腳本時,輸出為:
另外,連接類型為TCP表示可靠的數(shù)據(jù)流,可以有多個這樣的數(shù)據(jù)流,但彼此不受干擾。而其他協(xié)議如UDP、ICKMP、ARP則是非可靠的連接。也就是說,你可以一直接收和發(fā)送下去。
2. 發(fā)送數(shù)據(jù)
使用socket_send來發(fā)送數(shù)據(jù)。
創(chuàng)建 TCP Socket服務(wù)器
在服務(wù)器端使用命令行方式運行,在Linux中可用如下命令
也可以在系統(tǒng)守護進程中運行
通過使用以下命令殺死上面的進程
如果只創(chuàng)建一個TCP服務(wù)器實例,可以直接使用函數(shù)socket_create_listen()。
創(chuàng)建UDP服務(wù)器
UDP因為連接次數(shù)較少,處理比YCP簡單,一個UDP服務(wù)器只需要等待接收少量數(shù)據(jù),與客戶端在一個socket中發(fā)送數(shù)據(jù)而無需連接。
該UDP服務(wù)器可以處理多個客戶,但只是簡單地處理輸入后的返回信息。