本篇文章分享一個簡單的socket示例,用php。實現一個接收輸入字符串,處理并返回這個字符串到客戶端的TCP服務。
產生一個 socket 服務端
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?php /*文件名:socket_server.php*/ // 設置一些基本的變量 $host = "127.0.0.1" ; //Socket運行的服務器的IP地址 $port =1234; //Socket運行的服務器的端口,端口取值為1到65535之間的數字,前提是這個端口未被使用 // 設置超時時間,這里設置為永不超時,確保PHP在等待客戶端連接時不會超時。 set_time_limit(0); // 創建一個Socket,返回一個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" ); // 開始監聽外部連接 $result =socket_listen( $socket ,3) or die ( "Could not set up socket listener\n" ); /******到這里,服務器除了等待來自客戶端的連接請求外基本上什么也不做******/ // 另一個Socket來處理服務端與客戶端的通信 $spawn =socket_accept( $socket ) or die ( "Could not accept incoming connection\n" ); // 讀取客戶端的輸入,當一個連接被建立后,服務器就會等待客戶端發送一些輸入信息,這些信息可以由socket_read()函數來獲得,并把它賦值給PHP的$input變量 $input =socket_read( $spawn ,1024) or die ( "Could not read input\n" ); //socker_read的第二個參數用以指定讀入的字節數,你可以通過它來限制從客戶端獲取數據的大小 // 下面這不就不解釋了,不知道的自己面壁去 $input =trim( $input ); //處理客戶端輸入并返回結果,當客戶端發來數據信息后,信息輸出就要靠socket_write()函數來完成 $output = strrev ( $input ) . "\n" ; //反轉字符串,這里僅僅是為了更好的區分兩條信息 socket_write( $spawn , $output , strlen ( $output )) or die ( "Could not write output\n" ); // 關閉sockets socket_close( $spawn ); socket_close( $socket ); |
提示:你應該使用你的命令提示符來運行上面這段代碼。理由是因為這里將產生一個服務器,而不是一個Web頁面。如果你嘗試使用Web瀏覽器來運行這個腳本,那么很有可能它會超過30秒的限時。你可以使用下面的代碼來設置一個無限的運行時間,但是還是建議使用命令提示符來運行。
set_time_limit(0);
在你的命令提示符中對這個腳本進行簡單測試:
Php.exe socket_server.php
如果你沒有在系統的環境變量中設置php解釋器的路徑,那么你將需要給php.exe指定詳細的路徑。當你運行這個服務器端的時候,你能夠通過遠程登陸(telnet)的方式連接到端口1337來測試這個服務器。
上面的服務器端有三個問題:
1. 它不能接受多個連接。
2. 它只完成唯一的一個命令。
3. 你不能通過Web瀏覽器連接這個服務器。
這個第一個問題比較容易解決,你可以使用一個應用程序去每次都連接到服務器。但是后面的問題是你需要使用一個Web頁面去連接這個服務器,這個比較困難。你可以讓你的服務器接受連接,然后些數據到客戶端(如果它一定要寫的話),關閉連接并且等待下一個連接。
在上一個代碼的基礎上再改進,產生下面的代碼來做你的新服務器端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
<?php $commonProtocol = getprotobyname ( "tcp" ); $socket = socket_create(AF_INET, SOCK_STREAM, $commonProtocol ); socket_bind( $socket , 'localhost' , 1337); //socket_bind() 把socket綁定在一個IP地址和端口上 socket_listen( $socket ); $buffer = "NO DATA" ; while (true) { // Accept any connections coming in on this socket $connection = socket_accept( $socket ); //socket_accept() 接受一個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() 寫數據到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() 讀取指定長度的數據 $buffer = $data ; socket_write( $connection , "Information Received\r\n" ); printf( "Buffer: " . $buffer . "\r\n" ); } socket_close( $connection ); //socket_close() 關閉一個socket資源 printf( "Closed the socket\r\n\r\n" ); } |
這個服務器端要做什么呢?它初始化一個socket并且打開一個緩存收發數據。它等待連接,一旦產生一個連接,它將打印“Socket connected”在服務器端的屏幕上。這個服務器檢查緩沖區,如果緩沖區里有數據,它將把數據發送到連接過來的計算機。然后它發送這個數據的接受信息,一旦它接受了信息,就把信息保存到數據里,并且讓連接的計算機知道這些信息,最后關閉連接。當連接關閉后,服務器又開始處理下一次連接。
產生一個 socket 客戶端
處理第二個問題是很容易的。你需要產生一個php頁連接一個socket,發送一些數據進它的緩存并處理它。然后你有個處理后的數據在還頓,你能夠發送你的數據到服務器。在另外一臺客戶端連接,它將處理那些數據。
下面的例子示范了使用socket:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
<?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>" ); |
這個例子的代碼演示了客戶端連接到服務器。客戶端讀取數據。如果這是第一時間到達這個循環的首次連接,這個服務器將發送“NO DATA”返回給客戶端。如果情況發生了,這個客戶端在連接之上。客戶端發送它的數據到服務器,數據發送給服務器,客戶端等待響應。一旦接受到響應,那么它將把響應寫到屏幕上。