PHP的Socket編程

對(duì)于Socket編程首先需要先了解以下幾個(gè)知識(shí)點(diǎn):

1定页、什么是TCP/IP蜈抓、UDP驯妄、Http能耻、Socket帆竹?

TCP/IP(Transmission Control Protocol/Internet Protocol)即傳輸控制協(xié)議/網(wǎng)間協(xié)議绕娘,是一個(gè)工業(yè)標(biāo)準(zhǔn)的協(xié)議集,它是為廣域網(wǎng)(WANs)設(shè)計(jì)的栽连。

UDP(User Data Protocol险领,用戶數(shù)據(jù)報(bào)協(xié)議)是與TCP相對(duì)應(yīng)的協(xié)議。它是屬于TCP/IP協(xié)議族中的一種秒紧。

HTTP 協(xié)議即超文本傳送協(xié)議(Hypertext Transfer Protocol )绢陌,是Web聯(lián)網(wǎng)的基礎(chǔ),也是手機(jī)聯(lián)網(wǎng)常用的協(xié)議之一熔恢,HTTP協(xié)議是建立在TCP協(xié)議之上的一種應(yīng)用脐湾。

Socket 是對(duì)TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議叙淌,而是一個(gè)調(diào)用接口(API)沥割,通過(guò)Socket耗啦,我們才能使用TCP/IP協(xié)議。

Ps:
簡(jiǎn)單理解http是短鏈机杜,tcp是長(zhǎng)鏈帜讲,
短鏈?zhǔn)侨シ?wù)器拉數(shù)據(jù),長(zhǎng)鏈?zhǔn)欠?wù)器可以主動(dòng)推數(shù)據(jù)椒拗。

2似将、Socket是什么呢?

Socket就是應(yīng)用層與TCP/IP協(xié)議族通信的中間軟件抽象層蚀苛,它是一組接口在验。在設(shè)計(jì)模式中,Socket其實(shí)就是一個(gè)門面模式堵未,它把復(fù)雜的TCP/IP協(xié)議族隱藏在Socket接口后面腋舌,對(duì)用戶來(lái)說(shuō),一組簡(jiǎn)單的接口就是全部渗蟹,讓Socket去組織數(shù)據(jù)块饺,以符合指定的協(xié)議。

socket示意圖

PHP中的Socket

Socket擴(kuò)展是基于流行的BSD sockets雌芽,實(shí)現(xiàn)了和socket通訊功能的底層接口授艰,它可以和客戶端一樣當(dāng)做一個(gè)socket服務(wù)器。

PHP-Socket手冊(cè)

Socket相關(guān)函數(shù)

socket_accept() 接收一個(gè)socket連接
socket_bind() 把socket綁定在一個(gè)IP地址和端口上
socket_clear_error() 清除socket的錯(cuò)誤或者最后的錯(cuò)誤代碼
socket_close() 關(guān)閉一個(gè)socket資源
socket_connect() 開(kāi)始一個(gè)socket連接
socket_create_listen() 在指定端口打開(kāi)一個(gè)socket監(jiān)聽(tīng)
socket_create_pair() 產(chǎn)生一對(duì)沒(méi)有區(qū)別的socket到一個(gè)數(shù)組里
socket_create() 產(chǎn)生一個(gè)socket世落,相當(dāng)于產(chǎn)生一個(gè)socket的數(shù)據(jù)結(jié)構(gòu)
socket_get_option() 獲取socket選項(xiàng)
socket_getpeername() 獲取遠(yuǎn)程類似主機(jī)的ip地址
socket_getsockname() 獲取本地socket的ip地址
socket_iovec_add() 添加一個(gè)新的向量到一個(gè)分散/聚合的數(shù)組
socket_iovec_alloc() 這個(gè)函數(shù)創(chuàng)建一個(gè)能夠發(fā)送接收讀寫的iovec數(shù)據(jù)結(jié)構(gòu)
socket_iovec_delete() 刪除一個(gè)已經(jīng)分配的iovec
socket_iovec_fetch() 返回指定的iovec資源的數(shù)據(jù)
socket_iovec_free() 釋放一個(gè)iovec資源
socket_iovec_set() 設(shè)置iovec的數(shù)據(jù)新值
socket_last_error() 獲取當(dāng)前socket的最后錯(cuò)誤代碼
socket_listen() 監(jiān)聽(tīng)由指定socket的所有連接
socket_read() 讀取指定長(zhǎng)度的數(shù)據(jù)
socket_readv() 讀取從分散/聚合數(shù)組過(guò)來(lái)的數(shù)據(jù)
socket_recv() 從socket里結(jié)束數(shù)據(jù)到緩存
socket_recvfrom() 接受數(shù)據(jù)從指定的socket淮腾,如果沒(méi)有指定則默認(rèn)當(dāng)前socket
socket_recvmsg() 從iovec里接受消息
socket_select() 多路選擇
socket_send() 這個(gè)函數(shù)發(fā)送數(shù)據(jù)到已連接的socket
socket_sendmsg() 發(fā)送消息到socket
socket_sendto() 發(fā)送消息到指定地址的socket
socket_set_block() 在socket里設(shè)置為塊模式
socket_set_nonblock() socket里設(shè)置為非塊模式
socket_set_option() 設(shè)置socket選項(xiàng)
socket_shutdown() 這個(gè)函數(shù)允許你關(guān)閉讀、寫屉佳、或者指定的socket
socket_strerror() 返回指定錯(cuò)誤號(hào)的詳細(xì)錯(cuò)誤
socket_write() 寫數(shù)據(jù)到socket緩存
socket_writev() 寫數(shù)據(jù)到分散/聚合數(shù)組

Socket案例

server.php (服務(wù)器端)

<?php
/**
 * Socket服務(wù)端
 * author: flycorn
 * email: ym1992it@163.com
 * time: 16/12/27 下午3:43
 */
//設(shè)置無(wú)限請(qǐng)求超時(shí)時(shí)間
set_time_limit(0);

$ip = '127.0.0.1';
$port = 8099;

//創(chuàng)建socket
if(($sock = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {
    echo "socket_create() 失敗的原因是:".socket_strerror($sock)."\n";
    exit();
}
//把socket綁定在一個(gè)IP地址和端口上
if(($ret = socket_bind($sock,$ip,$port)) < 0) {
    echo "socket_bind() 失敗的原因是:".socket_strerror($ret)."\n";
    exit();
}
//監(jiān)聽(tīng)由指定socket的所有連接
if(($ret = socket_listen($sock,4)) < 0) {
    echo "socket_listen() 失敗的原因是:".socket_strerror($ret)."\n";
    exit();
}

//次數(shù)
$count = 0;

do{
    //接收一個(gè)Socket連接
    if (($msgsock = socket_accept($sock)) < 0) {
        echo "socket_accept() failed: reason: " . socket_strerror($msgsock) . "\n";
        break;
    } else {
        //發(fā)送到客戶端
        $msg = "測(cè)試成功! \n";
        socket_write($msgsock, $msg, strlen($msg));

        echo "測(cè)試成功了啊\n";
        // 獲得客戶端的輸入
        $buf = socket_read($msgsock, 2048);

        $talkback = "收到的信息:$buf\n";
        echo $talkback;

        //第5次結(jié)束
        if(++$count >= 5){
            break;
        }
    }
    //關(guān)閉socket
    socket_close($msgsock);
}while(true);

client.php (客戶端)

<?php
/**
 * Socket客戶端
 * author: flycorn
 * email: ym1992it@163.com
 * time: 16/12/27 下午4:03
 */
error_reporting(E_ALL);
//設(shè)置無(wú)限請(qǐng)求超時(shí)時(shí)間
set_time_limit(0);

echo "<h2>TCP/IP Connection</h2>\n";

$ip = '127.0.0.1';
$port = 8099;

//創(chuàng)建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 = '';

//寫數(shù)據(jù)到socket緩存
if(!socket_write($socket, $in, strlen($in))) {
    echo "socket_write() 失敗的原因是:".socket_strerror($sock)."\n";
    exit();
}
echo "發(fā)送到服務(wù)器信息成功谷朝!\n";
echo "發(fā)送的內(nèi)容為:$in \n";

//讀取指定長(zhǎng)度的數(shù)據(jù)
while($out = socket_read($socket, 2048)) {
    echo "接收服務(wù)器回傳信息成功!\n";
    echo "接收的內(nèi)容為:",$out;
}

echo "關(guān)閉SOCKET...\n";
socket_close($socket);
echo "關(guān)閉OK\n";

cli模式運(yùn)行:

1武花、打開(kāi)終端:php server.php

2徘禁、新開(kāi)一個(gè)終端:php client.php

3、服務(wù)端髓堪、客戶端分別會(huì)出現(xiàn)以下反饋:
服務(wù)端
客戶端

參考:
深入淺出講解:php的socket通信
sockets.examples

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市娘荡,隨后出現(xiàn)的幾起案子干旁,更是在濱河造成了極大的恐慌,老刑警劉巖炮沐,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件争群,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡大年,警方通過(guò)查閱死者的電腦和手機(jī)换薄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門玉雾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人轻要,你說(shuō)我怎么就攤上這事复旬。” “怎么了冲泥?”我有些...
    開(kāi)封第一講書人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵驹碍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我凡恍,道長(zhǎng)志秃,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任嚼酝,我火速辦了婚禮浮还,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘闽巩。我一直安慰自己钧舌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布又官。 她就那樣靜靜地躺著延刘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪六敬。 梳的紋絲不亂的頭發(fā)上碘赖,一...
    開(kāi)封第一講書人閱讀 52,874評(píng)論 1 314
  • 那天,我揣著相機(jī)與錄音外构,去河邊找鬼普泡。 笑死,一個(gè)胖子當(dāng)著我的面吹牛审编,可吹牛的內(nèi)容都是我干的撼班。 我是一名探鬼主播,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼垒酬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼砰嘁!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起勘究,我...
    開(kāi)封第一講書人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤矮湘,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后口糕,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體缅阳,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年景描,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了十办。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片秀撇。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖向族,靈堂內(nèi)的尸體忽然破棺而出呵燕,到底是詐尸還是另有隱情,我是刑警寧澤炸枣,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布虏等,位于F島的核電站,受9級(jí)特大地震影響适肠,放射性物質(zhì)發(fā)生泄漏霍衫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一侯养、第九天 我趴在偏房一處隱蔽的房頂上張望敦跌。 院中可真熱鬧,春花似錦逛揩、人聲如沸柠傍。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)惧笛。三九已至,卻和暖如春逞泄,著一層夾襖步出監(jiān)牢的瞬間患整,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工喷众, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留各谚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓到千,卻偏偏與公主長(zhǎng)得像昌渤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子憔四,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容