PHP通訊端編程

來源:互聯網
上載者:User
PHP通訊端編程

通訊端編程,一般使用c或c++。特別的在web應用程式開發中,常用perl實現通訊端。除此以外,用php進行通訊端編程也是一個選擇。Php可以勝任嗎。當然可以。Php是一門高品質的web應用程式開發語言,他的許多特性可以處理眾多的任務,網路編程也不例外。 

1. 理解通訊端 

Mail、ftp、telnet、name和finger這些服務都是在一個專用的公開的連接埠上提供的,通過串連到這些連接埠,客戶程式就能夠訪問這些服務。這與現實生活是相似的——當需要乾洗衣服的時候,找乾洗店;當需要取錢的時候,去銀行,等等。除了專用於特定伺服器的連接埠外,電腦還有其它的連接埠讓程式員建立他們自己的伺服器。 
連接埠一般是編號的,通過指定伺服器的連接埠號碼,客戶程式可以串連到該連接埠上。每種伺服器或連接埠要有特定的協議,為了讓客戶的請求能夠被理解和響應,客戶必須以這種伺服器特有的方式形成客戶請求。 
Socket是網路上啟動並執行兩個程式間雙向通訊串連的一端。Socket這個詞的一般意義是自然的或人工的插口,如家用電器的電源插口等。 
客戶程式可以向Socket寫請求,伺服器將處理此請求,然後通過Socket把結果返回給客戶。 
Socket是一種底層串連。客戶機和伺服器通過寫入到Socket的位元組流進行通訊。它們必須有共同的協議,也就是說,通過Socket相互傳送資訊時所用的語言必須是協定好的。 

2. Socket建立串連的過程 

建立過程如下:(connection-oriented)

server 方過程   client 方過程
socket()   socket()
bind()   bind()
listen()  
accept() connect()
recv() / send() ←→ send() / recv()


3. PHP 基本通訊端調用:  

3.1. )基本通訊端調用 

建立通訊端--socket(); 
綁定本機連接埠--bind(); 
建立串連--connect(),accept(); 
偵聽連接埠--listen(); 
資料轉送--send(),recv(); 
輸入/輸出多工--select(); 
關閉通訊端--closesocket() 

3.2. )php提供的通訊端調用: 

接受串連-—accept connect() 
綁定連接埠—bind () 
關閉通訊端—close() 
初始化串連—connect() 
偵聽連接埠—listen() 
讀取通訊端—read() 
建立通訊端—socket() 
寫通訊端—write() 

4. 基本應用 

4.1. )一個簡單的TCP伺服器
 

1 #!/usr/local/bin/php -q 

3 <?php 
4  /* 
5  * We don't want any time-limit for how the long can hang 
6  * around, waiting for connections:(使用set_time_limit設定程式執行時間為無限以等待串連) 
7  */ 
8 set_time_limit(0); 

10  /* Create a new socket: (建立一個通訊端)*/ 
11 if( ($sock = socket( AF_INET, SOCK_STREAM, 0 )) < 0 ) 
12 { 
13 print strerror( $sock ) . "n"; 
14 exit(1); 
15 } 
16 
17  /* Bind the socket to an address and a port: (把建立的通訊端與IP及連接埠綁定)*/ 
18 if( ($ret = bind( $sock, "10.31.172.77", 10000 )) < 0 ) 
19 { 
20 print strerror( $ret ) . "n"; 
21 exit(1); 
22 } 
23 
24  /* 
25  * Listen for incoming connections on $sock. 
26  * The '5' means that we allow 5 queued connections.(偵聽連接埠) 
27  */ 
28 if( ($ret = listen( $sock, 5 )) < 0 ) 
29 { 
30 print strerror( $ret ) . "n"; 
31 } 
32 
33  /* Accept incoming connections:(接受串連) */ 
34 if( ($msgsock = accept_connect( $sock )) < 0) 
35 { 
36 print strerror( $msgsock ) . "n"; 
37 exit(1); 
38 } 
39 
40  /* Send the welcome-message: (顯示歡迎資訊)*/ 
41 $message = "Welcome to my TCP-server!n"; 
42 if( ($ret = write( $msgsock, $message, strlen($message)) ) < 0 ) 
43 { 
44 print strerror( $msgsock ) . "n"; 
45 exit(1); 
46 } 
47 
48  /* Read/Receive some data from the client: (讀取用戶端資訊)*/ 
49 $buf = ''; 
50 if( ($ret = read( $msgsock, $buf, 128 )) < 0 ) 
51 { 
52 print strerror( $ret ) . "n"; 
53 exit(1); 
54 } 
55 
56  /* Echo the received data back to the client: (向用戶端回顯資訊)*/ 
57 if( ($ret = write( $msgsock, "You said: $bufn", strlen("You said: $bufn")) ) < 0 ) 
58 { 
59 print strerror( $ret ) . "n"; 
60 exit(1); 
61 } 
62 
63  /* Close the communication-socket: (關閉通訊端)*/ 
64 close( $msgsock ); 
65 
66 /* Close the global socket: */ 
67 close( $sock ); 
68 ?> 

4.2. )TCP伺服器的運行 

上邊這個tcp伺服器的運行要求php編譯成cgi解釋方式,並且編譯時間加入--enable-sockets。 
如果你已經編譯成cgi解釋方式運行,但是使用命令php -m列出的項目沒有sockets,則說明你需要重新編譯php。當這些要求達到後你就可以運行這個伺服器了 
啟動伺服器: 
./filename.php 
然後就可以使用telnet登入了。 
telnet 10.31.172.77 10000 
你的終端上將顯示: 
Trying 10.31.172.77... 
Connected to 10.31.172.77. 
Escape character is '^]'. 
Welcome to my TCP server! 
然後輸入一些東西,並斷行符號: 
Hello 
You said: Hello 
Connection closed by foreign host 

你也可以修改一下這個程式,讓它像phpmanual上的那個例子,只有當用戶端輸入“quit“的時候才關閉串連。 

5. 其他應用

5.1.) 聊天室應用 

5.1.1.> 常見的聊天室實現 

一般的聊天室的實現常使用的方法是使用架構頁面,然後對其中一個用於顯示談話內容的架構使用html的方式重新整理,例如: 
<meta http-equiv=“refresh” content=”3;http://www.jite.net”> 
使用這種方式會導致瀏覽器端不斷的向伺服器端發出請求,當有大量的請求時就會使得伺服器運行效率降低。這樣的聊天室顯然是有設計弊端的。 
但是如果使用socket的方式實現聊天室,情況就不同了。 

5.1.2.> 使用socket實現聊天室 

我們要討論的聊天室非常簡單,只是一個原理上的實現。 
它是一個 client/server 結構的程式, 首先啟動 server, 然後使用者使用 client 進行串連. client/server 結構的優點是速度快, 缺點是當 server 進行更新時, client 也必需更新. 

初始化 server, 使server 進入監聽狀態: (以下只是實現原理,並不涉及具體程式) 

$socket = socket( AF_INET,SOCK_STREAM, 0); 
// 首先建立一個 socket, 族為 AF_INET, 類型為 SOCK_STREAM. 
// AF_INET = ARPA Internet protocols 即使用 TCP/IP 協議族 
// SOCK_STREAM 類型提供了順序的, 可靠的, 基於位元組流的全雙工系統串連. 
// 由於該協議族中只有一個協議, 因此第三個參數為 0 

  
bind ($sock, $address, $port) 
// 再將這個 socket 與某個地址進行綁定. 

listen( sockfd, MAX_CLIENT) 
// 地址綁定之後, server 進入監聽狀態. 
// MAX_CLIENT 是可以同時建立串連的 client 總數. 

server 進入 listen 狀態後, 等待 client 建立串連。 

Client端要建立串連首先也需要初始化串連: 

$socket= socket( AF_INET,SOCK_STREAM,0)) 
// 同樣的, client 也先建立一個 socket, 其參數與 server 相同. 

connect ($socket, $address, $service_port) 
// client 使用 connect 建立一個串連. 

當 client 建立新串連的請求被送到Server端時, server 使用 accept 來接受該串連: 

accept_connect($sock) 
// accept 返回一個新的檔案描述符. 

在 server 進入 listen 狀態之後, 由於可能有多個使用者請求串連,所以程式需要同時對這些使用者進行操作,並在它們之間實現資訊交換。這在實現上稱為I/O多工技術。 
I/O多工技術的方法就不是本文所要敘述的內容了,如有興趣請參考相關書籍。 

5.2.) 一個基於web的新聞群組瀏覽器 

在php中可以使用fsockopen開啟一個tcp socket串連 
int fsockopen (string hostname, int port [, int errno [, string errstr [, double timeout]]]) 
有關此函數的使用請參考php手冊。 
訪問新聞群組服務,需要使用一個協議叫NNTP,即Network News Transfer Protocol。 
這個協議有一個專用的RFC描述,它位於 http://www.w3.org/Protocols/rfc977/rfc977.html。 
該文檔詳細的說明了如何同一個nntp伺服器對話及如何使用命令完成任務。 

5.2.1. > 串連一個伺服器 

<?php 
$cfgServer = "news.php.net"; 
$cfgPort = 119; 
$cfgTimeOut = 10; 

// open a socket 
if(!$cfgTimeOut) 
// without timeout 
$usenet_handle = fsockopen($cfgServer, $cfgPort); 
else 
// with timeout 
$usenet_handle = fsockopen($cfgServer, $cfgPort, &$errno, &$errstr, $cfgTimeOut); 

if(!$usenet_handle) { 
echo "Connexion failedn"; 
exit(); 

else { 
echo "Connectedn"; 
$tmp = fgets($usenet_handle, 1024); 

?> 

5.2.2. > 同伺服器進行對話 

在前面,我們已經同伺服器串連上了,假如我們要從某一新聞群組中選取10條最近的新聞,該怎麼辦呢。 
RFC977指出,選擇一個新聞群組使用group命令: 
GROUP ggg 
<?php 

//$cfgUser = "xxxxxx"; 
//$cfgPasswd = "yyyyyy"; 
$cfgNewsGroup = "alt.php"; 

// identification required on private server 
if($cfgUser) { 
fputs($usenet_handle, "AUTHINFO USER ".$cfgUser."n"); 
$tmp = fgets($usenet_handle, 1024); 

fputs($usenet_handle, "AUTHINFO PASS ".$cfgPasswd."n"); 
$tmp = fgets($usenet_handle, 1024); 

// check error 

if($tmp != "281 Okrn") { 
echo "502 Aut

hentication errorn"; 
exit(); 



// select newsgroup 

fputs($usenet_handle, "GROUP ".$cfgNewsGroup."n"); 
$tmp = fgets($usenet_handle, 1024); 

if($tmp == "480 Authentication required for commandrn") { 
echo "$tmpn"; 
exit(); 


$info = split(" ", $tmp); 
$first = $info[2]; 
$last = $info[3]; 

print "First : $firstn"; 
print "Last : $lastn"; 
?> 

5.2.3. > 讀取新聞 

讀取新聞的命令是article,具體用法請參考RFC977,這裡就不提供常式了。 

6. 後記 

我以為上次寫了一篇,這次就可以免了。離交稿日期沒幾天了,於榮賦來約稿。程稿倉促,難免有錯,請見諒,並且指出。 

7. 參考文獻: 

廖斌,《php的精靈編程》; 
w3c,《RFC977》; 
Daniel Solin,Introduction to Socket Programming with PHP;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.