首頁  >  文章  >  後端開發  >  PHP+Socket系列之實現客戶端與服務端資料傳輸

PHP+Socket系列之實現客戶端與服務端資料傳輸

藏色散人
藏色散人轉載
2023-02-02 11:35:014896瀏覽

這篇文章為大家帶來了關於php socket的相關知識,其中主要介紹了什麼是socket? php socket如何實現客戶端與服務端資料傳輸?有興趣的朋友下面一起來看一下,希望對大家有幫助。

socket介紹

實現網路進程之間的通信,幾乎所有應用程式都是採用socket,socket 是應用層與TCP/IP 協定族通訊的中間抽象層,它是一組介面。在設計模式中,socket 其實是個門面模式,它把複雜的TCP/IP 協定族隱藏在socket 介面後面,對使用者來說,一組簡單的介面就是全部,讓socket 去組織數據,以符合指定的協議

PHP+Socket系列之實現客戶端與服務端資料傳輸

socket 的英文原意是“孔”或“插座”,通常也被稱為“套接字”,用於描述IP 地址和端口,是一個通訊鏈的句柄,可以用來實現不同虛擬機器或不同電腦之間的通訊。

socket 連結的三個程序

  • 服務端監聽:IP 連接埠號碼

  • 客戶端請求:發出向服務端的IP 以及連接埠的連線請求

  • 連結確認:服務端套接字監聽到或說接收到客戶端套接字連線請求,他就會建立一個新的進程,把服務端的套接字描述發給客戶端,以回應客戶端的請求,一旦客戶端確認了此描述,連線就建立好了。兒服務端的套接字繼續處於監聽狀態,繼續接受其他客戶端套接字的連線請求。

PHP+Socket系列之實現客戶端與服務端資料傳輸

php實作socket

#如果需要在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 &#39;请求ip: &#39; . $ip . PHP_EOL . &#39;端口: &#39; . $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, &#39;127.0.0.1&#39;, 8888);

while (true) {
    // 让控制台输入内容
    fwrite(STDOUT, &#39;请输入内容:&#39;);
    $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 使用者指定目前套接字使用的類型

    ##SOCK_STREAM 可順序化的、可靠的、全雙工的、基於連結的位元組流,支援資料傳送流量控制機制。 TCP 協定是基於這種流式套接字。 SOCK_DGRAM資料封包的支援(無連線、不可靠、固定最大長度)UDP 協定是基於此封包套接字SOCK_SEQPACKET可順序化的、可靠的、全雙工的、面向連接的、固定最大長度的資料通信,資料端透過接收每一個資料段來讀取整個封包SOCK_RAW讀取原始的網路協議,這種特殊的套接字可用於手動建立任意類型的協議,一般使用這個套接字來實現ICMP 請求SOCK_RDM可靠的資料層,但不保證到達順序,一般的作業系統都未實現此功能#
  • protocol 设置指定 domain 套接字下的具体协议,如果所需协议是 TCP 或者 UDP,可以直接使用常量 SOL_TCPSOL_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.10.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_STREAMSOCK_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视频教程》                                                    

    type #描述

以上是PHP+Socket系列之實現客戶端與服務端資料傳輸的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:learnku.com。如有侵權,請聯絡admin@php.cn刪除