Socket以及Socket Php實例

socket的定義

socket,我們先僅僅看這個英文單詞的中文翻譯,它翻譯成:”孔”或者”插座”,擦,能不能稍微取個高雅點的名字!怎麼會是這個東西呢?這個留在後面,賣個關子,你會發現真的它就是個插座
既然socket就是插座,一般插座是長這樣的:
這裏寫圖片描述
我們從圖片中可以看到,它上面插了各種各樣電器的插頭,所有的電器都靠這個插座來供電和通訊。

所以插座就成了一個統一的接口,統一給所有的電器通電,所有的電器不需要了解電的原理,電的傳輸,電的各種。只要把電器的插頭插上去就可以通電工作使用了

回到網絡上的socket,同樣,和真實的插座一樣,它也是提供了一個統一的通訊接口,將底層的TCP/IP給封裝起來。需要通訊的進程,不需要了解TCP/IP是怎麼傳輸的,你只要用socket提供的插口,你就能通上電,就能將消息發出去!

socket,第一,它簡化了開發者的工作量,因爲協議衆多,進程衆多,全部自己去搞通訊底層是很效率低的。第二,統一了接口,使得不同原理的進程可以通過一個統一的socket進行通訊,比如德國人和中國人統一用英語就能友好溝通了。

蛋疼的官方定義:

Socket是應用層與TCP/IP協議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket接口後面,對用戶來說,一組簡單的接口就是全部,讓Socket去組織數據,以符合指定的協議。

什麼是TCP/IP

上面講到socket其實不是什麼協議,只是一個數據封裝,它封裝了TCP/IP的各種協議,然後提供接口的方式給用戶進程使用。那麼什麼是TCP/IP呢?

這邊講一下OSI七層模型以及Linux的TCP/IP概念層:
OSI包括 物理層 數據鏈路層 網絡層 傳輸層 會話層 表示層 應用層

這裏寫圖片描述

TCP/IP概念層是 物理層 數據鏈路層 網絡層 傳輸層 應用層

這裏寫圖片描述

TCP與UDP區別:

TCP—傳輸控制協議,提供的是面向連接、可靠的字節流服務。當客戶和服務器彼此交換數據前,必須先在雙方之間建立一個TCP連接,之後才能傳輸數據。TCP提供超時重發,丟棄重複數據,檢驗數據,流量控制等功能,保證數據能從一端傳到另一端。
UDP—用戶數據報協議,是一個簡單的面向數據報的運輸層協議。UDP不提供可靠性,它只是把應用程序傳給IP層的數據報發送出去,但是並不能保證它們能到達目的地。由於UDP在傳輸數據報前不用在客戶和服務器之間建立一個連接,且沒有超時重發等機制,故而傳輸速度很快(as3不支持udp)

用途

TCP一般用於文件傳輸(FTP HTTP 對數據準確性要求高,速度可以相對慢),發送或接收郵件(POP IMAP SMTP 對數據準確性要求高,非緊急應用),遠程登錄(TELNET SSH 對數據準確性有一定要求,有連接的概念)等等;UDP一般用於即時通信(QQ聊天 對數據準確性和丟包要求比較低,但速度必須快),在線視頻(RTSP 速度一定要快,保證視頻連續,但是偶爾花了一個圖像幀,人們還是能接受的),網絡語音電話(VoIP 語音數據包一般比較小,需要高速發送,偶爾斷音或串音也沒有問題)等等

這裏寫圖片描述

這裏寫圖片描述

socket 如何使用

我們平時都會打電話的吧。打電話就是一個非常好的理解和掌握socket的場景,我們想一想打電話是不是這樣:我想給周杰倫打電話,好久不見了。於是我先撥號,杰倫聽到電話鈴聲後提起電話,這時我和杰倫就建立起了連接,就可以講話了。等瞎比比結束,掛斷電話結束此次通話。

用socket的圖樣式給畫一下,就是這樣:

這裏寫圖片描述

socket 封裝了哪些接口

上面我們大致知道了socket是怎麼使用了,各種初始化啊,監聽啊什麼的。每個語言平臺都有不一樣的函數,但是都是基於socket封裝的接口的基礎上進行修改的。所以也是用到了socket提供的接口。

我們大致來看下PHP語言平臺下的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() 寫數據到分散/聚合數組

socket 的使用場景

既然socket是封裝了底層的TCP/IP,TCP/IP乾的又是通訊的活兒。所以,socket就特別是適合做通訊應用、有客戶機和服務器模式的通訊等應用。
1. 聊天室,多人聊天。
2. 實時性比較高的消息推送。
3. 客戶端與服務器之間通信。

socket 舉例說明

<?php
//socket 服務器端
/*
 +-------------------------------
 *    @創建socket server整個過程
 +-------------------------------
 *    @socket_create
 *    @socket_bind
 *    @socket_listen
 *    @socket_accept
 *    @socket_read
 *    @socket_write
 *    @socket_close
 +--------------------------------
 */
//設置不超時並打印所以錯誤
error_reporting(0);
set_time_limit(0);
//檢測php是否支持socket
if (!extension_loaded('sockets')) {
    die('The sockets extension is not loaded.');
    //需要打開擴展:extension=php_sockets.dll
}
//server的地址和端口
$address = "127.0.0.1";
$port = "10000";
//創建socket鏈接
$mysock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("Could not create socket\n");
//綁定地址和端口號
socket_bind($mysock, $address, $port) or die("Could not bind tosocket\n");
//監聽
socket_listen($mysock, 5) or die("Could not set up socket listener\n");;
echo "Server started, accepting connections...\n";
//Socket來處理通信。這裏會阻塞等待
$client = socket_accept($mysock) or die("Could not accept incomingconnection\n");
//發到客戶端
$msg ="congratulations! you success!\n";
socket_write($client, $msg, strlen($msg));
echo "send to client: $msg\n";
//接收客戶端的消息
$buf = socket_read($client, 8192);
echo "recvice from client: $buf\n"; 
//關閉
echo "Closing sockets...";
socket_close($client);
socket_close($mysock);
<?php
//socket 客戶端
/*
 +-------------------------------
 *    @client鏈接socket過程
 +-------------------------------
 *    @socket_create
 *    @socket_connect
 *    @socket_write
 *    @socket_read
 *    @socket_close
 +--------------------------------
 */
//設置不超時並打印所以錯誤
error_reporting(0);
set_time_limit(0);
//地址和端口號
$address = "127.0.0.1";
$port = 10000;
//創建socket鏈接
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
    echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n";
    die;
} else {
    echo "socket successfully created.\n";
}
//連接到地址和端口號
echo "Attempting to connect to '$address' on port '$port'...\n";
$result = socket_connect($socket, $address, $port);
if ($result === false) {
    echo "socket_connect() failed.\nReason: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
    die;
} else {
    echo "successfully connected to $address.\n";
}
//發給 server
$msg ="hello,I'm client\n";
socket_write($socket, $msg, strlen($msg));
echo "send to server: $msg\n";
//接收 server的消息
$buf = socket_read($socket, 8192);
echo "recvice from server: $buf\n";
echo "Closing socket...";
socket_close($socket);

先打開一個cmd運行 php server.php 就會阻塞掉,等待客戶端:

D:\wamp\www\testphp\socket>php server.php
server started, accepting connections...

再打開一個cmd 運行 php client.php 然後分別看client端和server端:
client端:

    D:\wamp\www\testphp\socket>php client.php
    socket successfully created.
    Attempting to connect to '127.0.0.1' on port '10000'...
    successfully connected to 127.0.0.1.
    send to server: hello,I'm client
    recvice from server: congratulations! you success!
    Closing socket...

server端:

    D:\wamp\www\testphp\socket>php server.php
    Server started, accepting connections...
    send to client: congratulations! you success!
    recvice from client: hello,I'm client
    Closing sockets...

參考資料:https://www.zybuluo.com/phper/note/47110

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章