1. 程式人生 > 實用技巧 >PHP socket 程式設計

PHP socket 程式設計

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