php簡(jiǎn)單socket服務(wù)器客戶端代碼實(shí)例
本篇文章分享一個(gè)簡(jiǎn)單的socket示例,用php。實(shí)現(xiàn)一個(gè)接收輸入字符串,處理并返回這個(gè)字符串到客戶端的TCP服務(wù)。
產(chǎn)生一個(gè) socket 服務(wù)端
<?php /*文件名:socket_server.php*/ // 設(shè)置一些基本的變量 $host="127.0.0.1";//Socket運(yùn)行的服務(wù)器的IP地址 $port=1234;//Socket運(yùn)行的服務(wù)器的端口,端口取值為1到65535之間的數(shù)字,前提是這個(gè)端口未被使用 // 設(shè)置超時(shí)時(shí)間,這里設(shè)置為永不超時(shí),確保PHP在等待客戶端連接時(shí)不會(huì)超時(shí)。 set_time_limit(0); // 創(chuàng)建一個(gè)Socket,返回一個(gè)Socket句柄 $socket=socket_create(AF_INET,SOCK_STREAM,0) or die("Could not create socket\n"); //綁定Socket到指定的地址和端口 $result=socket_bind($socket,$host,$port) or die("Could not bind to socket\n"); // 開始監(jiān)聽外部連接 $result=socket_listen($socket,3) or die("Could not set up socket listener\n"); /******到這里,服務(wù)器除了等待來自客戶端的連接請(qǐng)求外基本上什么也不做******/ // 另一個(gè)Socket來處理服務(wù)端與客戶端的通信 $spawn=socket_accept($socket) or die("Could not accept incoming connection\n"); // 讀取客戶端的輸入,當(dāng)一個(gè)連接被建立后,服務(wù)器就會(huì)等待客戶端發(fā)送一些輸入信息,這些信息可以由socket_read()函數(shù)來獲得,并把它賦值給PHP的$input變量 $input=socket_read($spawn,1024) or die("Could not read input\n"); //socker_read的第二個(gè)參數(shù)用以指定讀入的字節(jié)數(shù),你可以通過它來限制從客戶端獲取數(shù)據(jù)的大小 // 下面這不就不解釋了,不知道的自己面壁去 $input=trim($input); //處理客戶端輸入并返回結(jié)果,當(dāng)客戶端發(fā)來數(shù)據(jù)信息后,信息輸出就要靠socket_write()函數(shù)來完成 $output=strrev($input) ."\n";//反轉(zhuǎn)字符串,這里僅僅是為了更好的區(qū)分兩條信息 socket_write($spawn,$output,strlen($output)) or die("Could not write output\n"); // 關(guān)閉sockets socket_close($spawn); socket_close($socket);
提示:你應(yīng)該使用你的命令提示符來運(yùn)行上面這段代碼。理由是因?yàn)檫@里將產(chǎn)生一個(gè)服務(wù)器,而不是一個(gè)Web頁(yè)面。如果你嘗試使用Web瀏覽器來運(yùn)行這個(gè)腳本,那么很有可能它會(huì)超過30秒的限時(shí)。你可以使用下面的代碼來設(shè)置一個(gè)無限的運(yùn)行時(shí)間,但是還是建議使用命令提示符來運(yùn)行。
set_time_limit(0);
在你的命令提示符中對(duì)這個(gè)腳本進(jìn)行簡(jiǎn)單測(cè)試:
Php.exe socket_server.php
如果你沒有在系統(tǒng)的環(huán)境變量中設(shè)置php解釋器的路徑,那么你將需要給php.exe指定詳細(xì)的路徑。當(dāng)你運(yùn)行這個(gè)服務(wù)器端的時(shí)候,你能夠通過遠(yuǎn)程登陸(telnet)的方式連接到端口1337來測(cè)試這個(gè)服務(wù)器。
上面的服務(wù)器端有三個(gè)問題:
1. 它不能接受多個(gè)連接。
2. 它只完成唯一的一個(gè)命令。
3. 你不能通過Web瀏覽器連接這個(gè)服務(wù)器。
這個(gè)第一個(gè)問題比較容易解決,你可以使用一個(gè)應(yīng)用程序去每次都連接到服務(wù)器。但是后面的問題是你需要使用一個(gè)Web頁(yè)面去連接這個(gè)服務(wù)器,這個(gè)比較困難。你可以讓你的服務(wù)器接受連接,然后些數(shù)據(jù)到客戶端(如果它一定要寫的話),關(guān)閉連接并且等待下一個(gè)連接。
在上一個(gè)代碼的基礎(chǔ)上再改進(jìn),產(chǎn)生下面的代碼來做你的新服務(wù)器端:
<?php $commonProtocol = getprotobyname("tcp"); $socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol); socket_bind($socket, 'localhost', 1337); //socket_bind() 把socket綁定在一個(gè)IP地址和端口上 socket_listen($socket); $buffer = "NO DATA"; while(true) { // Accept any connections coming in on this socket $connection = socket_accept($socket);//socket_accept() 接受一個(gè)Socket連接 printf("Socket connected\r\n"); // Check to see if there is anything in the buffer if($buffer != ""){ printf("Something is in the buffer...sending data...\r\n"); socket_write($connection, $buffer . "\r\n"); //socket_write() 寫數(shù)據(jù)到socket緩存 printf("Wrote to socket\r\n"); }else { printf("No Data in the buffer\r\n"); } // Get the input while($data = socket_read($connection, 1024, PHP_NORMAL_READ)){//socket_read() 讀取指定長(zhǎng)度的數(shù)據(jù) $buffer = $data; socket_write($connection, "Information Received\r\n"); printf("Buffer: " . $buffer . "\r\n"); } socket_close($connection); //socket_close() 關(guān)閉一個(gè)socket資源 printf("Closed the socket\r\n\r\n"); }
這個(gè)服務(wù)器端要做什么呢?它初始化一個(gè)socket并且打開一個(gè)緩存收發(fā)數(shù)據(jù)。它等待連接,一旦產(chǎn)生一個(gè)連接,它將打印“Socket connected”在服務(wù)器端的屏幕上。這個(gè)服務(wù)器檢查緩沖區(qū),如果緩沖區(qū)里有數(shù)據(jù),它將把數(shù)據(jù)發(fā)送到連接過來的計(jì)算機(jī)。然后它發(fā)送這個(gè)數(shù)據(jù)的接受信息,一旦它接受了信息,就把信息保存到數(shù)據(jù)里,并且讓連接的計(jì)算機(jī)知道這些信息,最后關(guān)閉連接。當(dāng)連接關(guān)閉后,服務(wù)器又開始處理下一次連接。
產(chǎn)生一個(gè) socket 客戶端
處理第二個(gè)問題是很容易的。你需要產(chǎn)生一個(gè)php頁(yè)連接一個(gè)socket,發(fā)送一些數(shù)據(jù)進(jìn)它的緩存并處理它。然后你有個(gè)處理后的數(shù)據(jù)在還頓,你能夠發(fā)送你的數(shù)據(jù)到服務(wù)器。在另外一臺(tái)客戶端連接,它將處理那些數(shù)據(jù)。
下面的例子示范了使用socket:
<?php // Create the socket and connect $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $connection = socket_connect($socket,'localhost', 1337); while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)) { if($buffer == "NO DATA") { echo("<p>NO DATA</p>"); break; }else{ // Do something with the data in the buffer echo("<p>Buffer Data: " . $buffer . "</p>"); } } echo("<p>Writing to Socket</p>"); // Write some test data to our socket if(!socket_write($socket, "SOME DATA\r\n")){ echo("<p>Write failed</p>"); } // Read any response from the socket phpernote.com while($buffer = socket_read($socket, 1024, PHP_NORMAL_READ)){ echo("<p>Data sent was: SOME DATA<br> Response was:" . $buffer . "</p>"); } echo("<p>Done Reading from Socket</p>");
這個(gè)例子的代碼演示了客戶端連接到服務(wù)器。客戶端讀取數(shù)據(jù)。如果這是第一時(shí)間到達(dá)這個(gè)循環(huán)的首次連接,這個(gè)服務(wù)器將發(fā)送“NO DATA”返回給客戶端。如果情況發(fā)生了,這個(gè)客戶端在連接之上??蛻舳税l(fā)送它的數(shù)據(jù)到服務(wù)器,數(shù)據(jù)發(fā)送給服務(wù)器,客戶端等待響應(yīng)。一旦接受到響應(yīng),那么它將把響應(yīng)寫到屏幕上。
- 用PHP的socket實(shí)現(xiàn)客戶端到服務(wù)端的通信實(shí)例詳解
- 深入淺出講解:php的socket通信原理
- php socket通信簡(jiǎn)單實(shí)現(xiàn)
- php socket通信(tcp/udp)實(shí)例分析
- PHP的Socket通信之UDP通信實(shí)例
- php中socket通信機(jī)制實(shí)例詳解
- php與flash as3 socket通信傳送文件實(shí)現(xiàn)代碼
- php與java通過socket通信的實(shí)現(xiàn)代碼
- php socket客戶端及服務(wù)器端應(yīng)用實(shí)例
- PHP基于socket實(shí)現(xiàn)的簡(jiǎn)單客戶端和服務(wù)端通訊功能示例
相關(guān)文章
PHP生成二維碼與識(shí)別二維碼的方法詳解【附源碼下載】
這篇文章主要介紹了PHP生成二維碼與識(shí)別二維碼的方法,結(jié)合實(shí)例形式分析了php二維碼相關(guān)概念、原理及生成、識(shí)別二維碼相關(guān)操作技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下2019-03-03PHP查詢并刪除數(shù)據(jù)庫(kù)多列重復(fù)數(shù)據(jù)的方法(利用數(shù)組函數(shù)實(shí)現(xiàn))
這篇文章主要介紹了PHP查詢并刪除數(shù)據(jù)庫(kù)多列重復(fù)數(shù)據(jù)的方法,利用數(shù)組函數(shù)實(shí)現(xiàn)該功能,涉及PHP數(shù)據(jù)庫(kù)操作的相關(guān)技巧,需要的朋友可以參考下2016-02-02DW中鏈接mysql數(shù)據(jù)庫(kù)時(shí),建立字符集中文出現(xiàn)亂碼的解決方法
DW中鏈接mysql數(shù)據(jù)庫(kù)時(shí),建立字符集中文出現(xiàn)亂碼“????”2010-03-03PHP跳出for循環(huán)中的break和continue
在PHP中,可以使用break關(guān)鍵字來跳出循環(huán),,PHP中還可以使用continue關(guān)鍵字跳過本次循環(huán)并繼續(xù)執(zhí)行下一次循環(huán),當(dāng)循環(huán)執(zhí)行到continue語句時(shí),本次循環(huán)中continue之后的代碼將不再執(zhí)行,直接進(jìn)入下一次循環(huán)2023-09-09