最近在做的項目有一項需要耗時任務在後台啟動並執行功能,雖然PHP並不是非常適合做常駐背景守護進程,但是由於項目主要代碼都是基於PHP實現,如果運行在背景守護進程改換別的語言會非常不方便。所以不可避免會涉及到Web端和Daemon部分的通訊,Socket是一個不錯的方式。
Socket是什麼
socket的英文原義是“孔”或“插座”。作為BSD UNIX的進程通訊機制,取後一種意思。通常也稱作”通訊端”,用於描述IP地址和連接埠,是一個通訊鏈的控制代碼。在Internet上的主機一般運行了多個服務軟體,同時提供幾種服務。每種服務都開啟一個Socket,並綁定到一個連接埠上,不同的連接埠對應於不同的服務。
以上內容來自百度百科
簡單說來,socket可以協助不同的服務在不同的連接埠進行通訊。
PHP中的實現
服務端
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
42
43
44
set_time_limit(0);
// 設定主機和連接埠
$host = "127.0.0.1" ;
$port = 12387;
// 建立一個tcp流
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
or die ( "socket_create() failed:" . socket_strerror(socket_last_error()));
// 設定阻塞模式
socket_set_block( $socket )
or die ( "socket_set_block() failed:" . socket_strerror(socket_last_error()));
// 綁定到連接埠
socket_bind( $socket , $host , $port )
or die ( "socket_bind() failed:" . socket_strerror(socket_last_error()));
// 開始監聽
socket_listen( $socket , 4)
or die ( "socket_listen() failed:" . socket_strerror(socket_last_error()));
echo "Binding the socket on $host:$port ... \n" ;
while (true) {
// 接收串連請求並調用一個子串連Socket來處理用戶端和伺服器間的資訊
if (( $msgsock = socket_accept( $socket )) < 0) {
echo "socket_accept() failed:" . socket_strerror(socket_last_error());
} else {
// 讀資料
$out = '' ;
while ( $buf = socket_read( $msgsock ,8192)){
$out .= $buf ;
}
// 寫資料
$in = "資料是 $out" ;
socket_write( $msgsock , $in , strlen ( $in ));
}
// 結束通訊
socket_close( $msgsock );
}
socket_close( $socket );
?>
服務端主要進行了以下步驟:
建立Socket的監聽,等待串連
當連結到來時,開啟一個子串連處理IO
接收來自用戶端的傳輸資料
將結果寫回給用戶端
用戶端
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
set_time_limit(0);
$host = "127.0.0.1" ;
$port = 12387;
// 建立一個tcp流
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
or die ( "socket_create() failed:" . socket_strerror(socket_last_error()));
echo "try to connect to $host:$port...\n" ;
$result = socket_connect( $socket , $host , $port )
or die ( "socket_connect() failed:" . socket_strerror(socket_last_error()));
$in = "hello \n" ;
if (!socket_write( $socket , $in , strlen ( $in ))) {
echo "socket_write() failed:" . socket_strerror( $socket );
} else {
echo "發送成功!\n" ;
}
$out = '' ;
while ( $buf = socket_read( $socket , 8192)) {
$out .= $buf ;
}
echo "接受內容為:$out \n" ;
socket_close( $socket );
?>
用戶端主要有以下步驟:
串連到服務端Socket
向服務端寫資料
接收來自服務端的資料