Socket介紹
什麼是socket 所謂socket通常也稱作"套接字",用于描述IP位址和端口,是一個通信鍊的句柄。應用程式通常通過"套接字"向網絡送出請求或者應答網絡請求。
在Internet上的主機一般運作了多個服務軟體,同時提供幾種服務。每種服務都打開一個Socket,并綁定到一個端口上,不同的端口對應于不同的服務。
Socket連接配接過程
根據連接配接啟動的方式以及本地套接字要連接配接的目标,套接字之間的連接配接過程可以分為三個步驟:伺服器監聽,用戶端請求,連接配接确認。
(1)伺服器監聽:是伺服器端套接字并不定位具體的用戶端套接字,而是處于等待連接配接的狀态,實時監控網絡狀态。
(2)用戶端請求:是指由用戶端的套接字提出連接配接請求,要連接配接的目标是伺服器端的套接字。為此,用戶端的套接字必須首先描述它要連接配接的伺服器的套接字,指出伺服器端套接字的位址和端口号,然後就向伺服器端套接字提出連接配接請求。
(3)連接配接确認:是指當伺服器端套接字監聽到或者說接收到用戶端套接字的連接配接請求,它就響應用戶端套接字的請求,建立一個新的線程,把伺服器端套接字的描述發給用戶端,一旦用戶端确認了此描述,連接配接就建立好了。而伺服器端套接字繼續處于監聽狀态,繼續接收其他用戶端套接字的連接配接請求
1、測試環境:
伺服器ip:192.168.150.1
用戶端ip:192.168.150.2
2、測試過程:
用戶端伺服器将在本機(192.168.150.2)通過socket發送資料到服務端(192.168.150.2)的socket伺服器上,服務端接收到用戶端發送的資料後傳回一些資訊給用戶端。
3、服務端檔案内容:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<code>#server.php</code>
<code><?php </code>
<code>//擷取tcp協定号碼。</code>
<code>$tcp</code> <code>= </code><code>getprotobyname</code><code>(</code><code>"tcp"</code><code>); </code>
<code>// 建立server端socket ,建立并傳回一個套接字,也稱作一個通訊節點。一個典型的網絡連接配接由 2 個套接字構成,一個運作在用戶端,另一個運作在伺服器端。</code>
<code>$socket</code> <code>= socket_create(AF_INET, SOCK_STREAM, </code><code>$tcp</code><code>); </code>
<code>//綁定要監聽的ip和端口,這裡綁定的ip一定要寫區域網路ip,寫成127.0.0.1用戶端将無法與服務端建議連接配接。</code>
<code>socket_bind(</code><code>$socket</code><code>, </code><code>'192.168.150.1'</code><code>, 10008); </code>
<code> </code><code>//監聽端口 </code>
<code>socket_listen(</code><code>$socket</code><code>); </code>
<code> </code>
<code>//初始化一個資料,和用戶端通信 </code>
<code>$buffer</code> <code>= </code><code>"connect"</code><code>; </code>
<code>while</code> <code>(true) { </code>
<code> </code><code>// 接受用戶端請求過來的一個socket連接配接 </code>
<code> </code><code>$connection</code> <code>= socket_accept(</code><code>$socket</code><code>); </code>
<code> </code><code>if</code><code>(!</code><code>$connection</code><code>){ </code>
<code> </code><code>echo</code> <code>"connect faild"</code><code>; </code>
<code> </code><code>}</code><code>else</code><code>{ </code>
<code> </code><code>echo</code> <code>"Socket connected\n"</code><code>; </code>
<code> </code><code>// 向用戶端傳遞一個資訊資料 </code>
<code> </code><code>if</code> <code>(</code><code>$buffer</code> <code>!= </code><code>""</code><code>) { </code>
<code> </code><code>echo</code> <code>"send data to client\n"</code><code>; </code>
<code> </code><code>socket_write(</code><code>$connection</code><code>, </code><code>$buffer</code> <code>. </code><code>"\n"</code><code>); </code>
<code> </code><code>echo</code> <code>"Wrote to socket\n"</code><code>; </code>
<code> </code><code>} </code><code>else</code> <code>{ </code>
<code> </code><code>echo</code> <code>"no data in the buffer\n"</code> <code>; </code>
<code> </code><code>} </code>
<code> </code><code>// 從用戶端擷取得的資料</code>
<code> </code><code>while</code> <code>(</code><code>$data</code> <code>= @socket_read(</code><code>$connection</code><code>, 1024, PHP_NORMAL_READ)) { </code>
<code> </code><code>printf(</code><code>"Buffer: "</code> <code>. </code><code>$data</code> <code>. </code><code>"\n"</code><code>); </code>
<code> </code><code>//取得資訊給用戶端一個回報, Thank you client, you data is Received success發給用戶端的回應資訊。</code>
<code> </code><code>socket_write(</code><code>$connection</code><code>, </code><code>"Thank you client, you data is Received success\n"</code><code>); </code>
<code> </code><code>} </code>
<code> </code><code>//關閉 socket</code>
<code> </code><code>socket_close(</code><code>$connection</code><code>); </code>
<code> </code><code>printf(</code><code>"Closed the socket\n"</code><code>); </code>
<code>} </code>
<code>?></code>
<code>4、用戶端檔案内容:</code>
<code>client.php</code>
<code>// 建立用戶端的socet連接配接 </code>
<code>$socket</code> <code>= socket_create(AF_INET, SOCK_STREAM, SOL_TCP); </code>
<code> </code><code>//連接配接伺服器端socket </code>
<code>$connection</code> <code>= socket_connect(</code><code>$socket</code><code>, </code><code>'192.168.150.1'</code><code>, 10008); </code>
<code>//要發送到服務端的資訊。</code>
<code>$send_data</code> <code>= </code><code>"This data will Send to server!"</code><code>;</code>
<code>//用戶端去連接配接服務端并接受服務端傳回的資料,如果傳回的資料保護not connect就提示不能連接配接。</code>
<code>while</code> <code>(</code><code>$buffer</code> <code>= @socket_read(</code><code>$socket</code><code>, 1024, PHP_NORMAL_READ)) { </code>
<code> </code><code>if</code> <code>(preg_match(</code><code>"/not connect/"</code><code>,</code><code>$buffer</code><code>)) { </code>
<code> </code><code>echo</code> <code>"don`t connect\n"</code><code>; </code>
<code> </code><code>break</code><code>; </code>
<code> </code><code>} </code><code>else</code> <code>{ </code>
<code> </code><code>//服務端傳來的資訊 </code>
<code> </code><code>echo</code> <code>"Buffer Data: "</code> <code>. </code><code>$buffer</code> <code>. </code><code>"\n"</code><code>; </code>
<code> </code><code>echo</code> <code>"Writing to Socket\n"</code><code>; </code>
<code> </code><code>// 将客戶的資訊寫到通道中,傳給伺服器端 </code>
<code> </code><code>if</code> <code>(!socket_write(</code><code>$socket</code><code>, </code><code>"$send_data\n"</code><code>)) { </code>
<code> </code><code>echo</code> <code>"Write failed\n"</code><code>; </code>
<code> </code><code>} </code>
<code> </code><code>//伺服器端收到資訊後,用戶端接收服務端傳給用戶端的回應資訊。 </code>
<code> </code><code>while</code> <code>(</code><code>$buffer</code> <code>= socket_read(</code><code>$socket</code><code>, 1024, PHP_NORMAL_READ)) { </code>
<code> </code><code>echo</code> <code>"sent to server:$send_data\n response from server was:"</code> <code>. </code><code>$buffer</code> <code>. </code><code>"\n"</code><code>; </code>
<code> </code><code>} </code>
5、在服務端socket服務啟動程序。
#/usr/local/php/bin/php -a /home/server.php
Interactive mode enabled
6、服務端啟動後檢視啟動的程序及端口。
#netstat -tnlp |grep 10008
tcp 0 0 192.168.150.13:10008 0.0.0.0:* LISTEN 28892/php
7、在用戶端(192.168.1.2)上執行傳輸
#/usr/local/php/bin/php -a client.php
Buffer Data: connect
Writing to Socket
sent to server:This data will Send to server!
response from server was:Thank you client, you data Information Received
8、回到服務端上檢視接收到的資訊。
Socket connected
send data to client
Wrote to socket
Buffer: This data will Send to server!
9、參考資料
socket_create()函數需要三個參數:一個協定、一個socket類型、一個公共協定。socket_create()函數運作成功傳回一個包含socket的資源類型,如果沒有成功則傳回false。
Socket函數
函數名 描述
socket_accept() 接受一個Socket連接配接
socket_bind() 把socket綁定在一個IP位址和端口上
socket_close() 關閉一個socket資源
socket_connect() 開始一個socket連接配接
socket_create() 産生一個socket,相當于産生一個socket的資料結構
socket_listen() 監聽由指定socket的所有連接配接
socket_read() 讀取指定長度的資料
socket_readv() 讀取從分散/聚合數組過來的資料
socket_send() 這個函數發送資料到已連接配接的socket
socket_write() 寫資料到socket緩存
socket_writev() 寫資料到分散/聚合數組
參考文檔:http://blog.51yip.com/php/673.html
本文轉自 張玉坡 51CTO部落格,原文連結:http://blog.51cto.com/fighter/1533957