標籤:配置 fine 簡單 highlight 連接埠 exe create led 存在
在網路中資料傳播分為:Unicast(單播) , Multicast(多播或者組播) 和 Broadcast(廣播)。廣播和多播僅應用於UDP,它們對需將報文同時傳往多個接收者的應用來說十分重要。而 TCP 是一個連線導向的協議,它意味著分別運行於兩主機(由IP地址確定)內的兩進程(由連接埠號碼確定)間存在一條串連。廣播位址在預設情況下是不能讓路由器轉寄到別的介面的,廣播不能穿越路由器。廣播有以下幾種形式:
受限的廣播位址是255.255.255.255,該地址用於主機配置過程中IP資料報的地址,此時,主機可能還不知道它所在網路的網路遮罩,甚至連它的IP地址也不知道。在任何情況下,路由器都不轉寄目的地址為受限廣播位址的資料報,這樣的資料報只出現在本網中。
指向網路的廣播位址是主機號全為1的地址,A類網路廣播位址為netid.255.255.255,其中netid為A類網路的網路號。
指向子網的廣播位址是主機號全為1的地址,作為子網直接廣播的IP地址需要知道子網的掩碼。如果B類網路128.1的子網路遮罩是255.255.255.0,則地址128.1.2.255就是對應子網的廣播位址。
指向所有子網的廣播也需要知道目的網路的子網路遮罩。這些廣播位址的子網號和主機號全為1。如果目的子網路遮罩是255.255.255.0,那麼IP地址128.1.255.255就是一個指向所有子網的廣播位址。
PHP socket 也能實現廣播。在 socket 通訊中,實現已連線的服務器與用戶端需要綁定同一連接埠號碼,連接埠號碼表示發送和接收的進程。下面是一個用 PHP 實現的簡單的廣播通訊例子,同時採用 PHP 和 C 語言作為用戶端進行測試:
<?php # Script -- broadcast.php/* Author @ Huoty * Date @ 2015-11-17 09:58:25 * Brief @ *//* 建立廣播事件 */function broadcast(){ $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); //使用IPV4格式地址,資料報形式,UDP方式傳輸資料 socket_set_option($sock, SOL_SOCKET, SO_BROADCAST, 1); //設定為廣播方式 while ( true ) { $msg = ‘Hi! ‘ . date("y-m-d h:i:s",time()); //要發送的字串 socket_sendto($sock, $msg, strlen($msg), 0, "255.255.255.255", 12345); //發送,255.255.255.255是廣播位址,12345是連接埠 //echo "Broadcast...\n"; sleep( 2 ); } socket_close($sock); //關閉}/* 建立守護進程 */$pid = pcntl_fork();if ($pid < 0){ die("fork failed!\n");}else if ($pid > 0){ exit;}else{ /* 輸出進程ID,便於 kill */ echo "Daemons ID: " . posix_getpid() . "\n"; /* 保持程式的運行 */ set_time_limit(0); /* 建立一個新的 Session */ $sid = posix_setsid(); if ($sid < 0) { exit; } /* 改變工作目錄為根目錄 */ chdir("/"); broadcast();}?>
<?php # Script -- client.php/* Author @ Huoty * Date @ 2015-11-17 09:58:25 * Brief @ *///error_reporting( E_ALL );set_time_limit( 0 );ob_implicit_flush();$socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );if ( $socket === false ) { echo "socket_create() failed:reason:" . socket_strerror( socket_last_error() ) . "\n";}$ok = socket_bind( $socket, ‘255.255.255.255‘, 12345 );if ( $ok === false ) { echo "socket_bind() failed:reason:" . socket_strerror( socket_last_error( $socket ) );}while ( true ) { $from = ""; $port = 0; socket_recvfrom( $socket, $buf, 1024, 0, $from, $port ); echo $buf . "\n"; usleep( 1000 );}?>
/* client.c */#include <stdio.h>#include <string.h>#include <unistd.h>#include <netinet/in.h>#define MAXLINE 80#define SERV_PORT 12345int main(int argc, char *argv[]){ struct sockaddr_in servaddr; int sockfd, n; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; socklen_t servaddr_len; sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); fprintf(stdout, "Accepting connections ...\n"); memset(buf, 0, sizeof(buf)); while ( 1 ) { n = recvfrom(sockfd, buf, MAXLINE, 0, NULL, 0); if (n == -1) fprintf(stderr, "recvfrom error"); fprintf(stdout, "%s\n", buf); memset(buf, 0, sizeof(buf)); } close(sockfd); return 0;}
通常,廣播是需要長時間進行的任務,所以可以建立一個守護進程來完成廣播,以避免程式長時間運行對控制終端的佔用。如果不使用守護進程,也可以用 Linux 的 nohup
命令來實現。然而,PHP 的進程式控制制不能被應用在 Web 服務器環境。那麼,要讓 PHP 的進程式控制制在 Web 環境下得到應用,可以用一個迂迴的辦法,即用 cli
的方式執行包含進程式控制制的 PHP 檔案,所謂 cli 方式是指 shell 的執行方式。還有一個需要注意的問題是,在 Web 環境下,由於 PHP 程式是一個死迴圈,程式一直運行,所以用戶端總是得不到伺服器的返回結果。為解決這個問題,可以將用 &
讓程式在後台運行,同時將輸出重新導向到 /dev/null
。於是可以建立了一個新檔案以保證廣播在 Web 服務器環境下能夠被觸發:
<?php # Script -- startup.php/* Author @ Huoty * Date @ 2015-12-02 16:53:43 * Brief @ */exec("php ./broadcast_daemons.php >/dev/null &");echo "Finished!";?>
PHP向用戶端廣播資訊