<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                ![](https://img.kancloud.cn/32/54/325416ac992c75d9988b46f3514f8aea_489x482.png) ![](https://img.kancloud.cn/20/02/200263efa9bc263a635ae08f16f8d331_427x219.png) 具體參看[socket擴展函數](http://www.hmoore.net/a173512/php_note/1690702) ## php如何創建服務器socket? 創建socket,設置socket選項,socket綁定ip和端口,socket監聽 ``` // 創建一個 TCP socket, 此函數的可選值在官方文檔中寫得十分詳細,這里不再提了 $this->master = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); // 設置IP和端口重用,在重啟服務器后能重新使用此端口; socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1); // 將IP和端口綁定在服務器socket上; socket_bind($this->master, $host, $port); // listen函數使主動連接套接口變為被連接套接口,使得此 socket 能被其他 socket 訪問,從而實現服務器功能。后面的參數則是自定義的待處理socket的最大數目,并發高的情況下,這個值可以設置大一點,雖然它也受系統環境的約束。 socket_listen($this->master, self::LISTEN_SOCKET_NUM); ``` ## 關鍵函數 <span style="color:blue">**socket_create**</span>($net參數1網絡協議,$stream參數2套接字流,$protocol參數3protocol協議) 作用:創建一個socket套接字,說白了,就是一個網絡數據流。 返回值:一個套接字,或者是false,參數錯誤發出E\_WARNING警告 <span style="color:blue">**socket_connect**</span>($socket參數1socket\_create的函數返回值,$ip參數2ip地址,$port參數3端口號) 作用:連接一個套接字,返回值為true或者false 參數1:socket_create的函數返回值 <span style="color:blue">**socket_bind**</span>($socket參數1socket\_create的函數返回值,$ip參數2ip地址,$port參數3端口號) 作用:綁定一個套接字,返回值為true或者false <span style="color:blue">**socket_listen**</span>($socket參數1socket_create的函數返回值,$backlog?參數2最大監聽套接字個數) 作用:監聽一個套接字,返回值為true或者false <span style="color:blue">**socket_accept**</span>($socket參數1socket\_create的函數返回值) 作用:接收(客戶端)套接字的資源信息,成功返回套接字的信息資源,失敗為false,默認是阻塞的他會一直等待客戶端的鏈接,如果有多個客戶端等待連接則先與第一個通信,其他會阻塞的等待著。如果`socket`已使用[socket\_set\_blocking()](https://www.php.net/manual/en/function.socket-set-blocking.php)或[socket\_set\_nonblock()](https://www.php.net/manual/en/function.socket-set-nonblock.php)進行了非阻塞,則將返回 **`FALSE`** 可以通過調用[socket\_last\_error()](https://www.php.net/manual/en/function.socket-last-error.php)來檢索實際的錯誤代碼。可以將此錯誤代碼傳遞給[socket\_strerror()](https://www.php.net/manual/en/function.socket-strerror.php)以獲得錯誤的文本說明 >[info]有客戶端從很遠的地方通過服務端偵聽(socket_listen)的端口連接(socket_connect)到你的服務器。它的連接將加入到等待接受(socket_accept)的隊列中。服務器通過socket_accept告訴它服務器有空閑的連接了其他的客戶端先等待著。客戶端將返回一個它的套接字給socket_accept!這樣你就有兩個套接字了,原來服務端的那個還在一直偵聽你的那個端口, 新的這個在準備發送(socket_send)和接收(socket_recv)數據。 <span style="color:blue">**socket_read**</span>($socket參數1socket_create或者socket_accept的函數返回值,$length參數2讀取的字符串的長度) 作用:讀取套接字的資源信息, 返回值:成功把套接字的資源轉化為字符串信息,失敗為false <span style="color:blue">**socket_write**</span>($socket參數1socket\_create或者socket\_accept的函數返回值,$msg參數2字符串,$strlen參數3字符串的長度) 作用:把數據寫入套接字中 返回值:成功返回字符串的字節長度,失敗為false <span style="color:blue">**socket_close**</span>($socket參數1socket\_create或者socket\_accept的函數返回值) 作用:關閉套接字 返回值:成功返回true,失敗為false <span style="color:blue">**ocket_set_option**</span>s($socket參數1socket\_create或者socket_accept的函數返回值?,$level?參數2 SOL_SOCKET,可以通過使用[getprotobyname()](https://www.php.net/manual/en/function.getprotobyname.php)函數找到,$optname?參數3參數4是相關聯的[optname可選項](https://www.php.net/manual/en/function.socket-get-option.php),$optval?參數4) ``` server.php <?php $socket=socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); if (!socket_bind($socket,'127.0.0.1',8080)) { echo "綁定失敗".socket_strerror(socket_last_error()); } if (!socket_listen($socket,4)) { echo "監聽失敗".socket_strerror(socket_last_error()); } $client_socket = socket_accept($socket); //默認阻塞的 socket_write($client_socket, '找到客戶端并監聽起啦', strlen('找到客戶端并監聽起啦')); $result=socket_read($client_socket,1024); if (!empty($result)&&$result=="我來啦") { echo mb_convert_encoding("接受到客戶端數據\r\n",'gbk'); socket_write($client_socket, '我接受到數據啦', strlen('我接受到數據啦')); } socket_close($socket); socket_close($client_socket); client.php <?php $socket=socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); if (!socket_connect($socket,'127.0.0.1', 8080)) { echo '鏈接失敗'.socket_strerror(socket_last_error()); } if (socket_read($socket,1024)=="找到客戶端并監聽起啦") { echo mb_convert_encoding("我來啦!\r\n",'gbk'); socket_write($socket,'我來啦', strlen('我來啦')); } if (socket_read($socket,1024)=="我接受到數據啦") { echo mb_convert_encoding("我接受到數據啦!\r\n",'gbk'); } socket_close($socket); ``` ![](https://img.kancloud.cn/eb/3d/eb3d692971c009b2c0ba6d9d60157b2a_435x53.png) ![](https://img.kancloud.cn/ba/1f/ba1f0c3f91ae2523172190c5e2c16b71_457x72.png) ## TCP客戶端和TCP服務器端之間非常簡單的交互 ``` // create for simple-tcp-server $sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); socket_bind($sock, '127.0.0.1',5000); socket_listen($sock,1); $clnt_sock = socket_accept($sock); //阻塞 $st = "hello world ^_^"; socket_write($clnt_sock, $st,strlen($st)); socket_close($clnt_sock); socket_close($sock); ?> <?php //create for simple-tcp-client $clnt_sock = socket_create(AF_INET, SOCK_STREAM, getprotobyname('tcp')); socket_connect($clnt_sock, '127.0.0.1', 5000); $ret= socket_read($clnt_sock, 1024); print "from simple-tcp-server:".$ret.PHP_EOL; socket_close($clnt_sock); ?> ``` ``` //如果要在一臺服務器上有多個客戶端,則必須使用非阻塞 $clients = array(); $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); socket_bind($socket,'127.0.0.1',$port); socket_listen($socket); socket_set_nonblock($socket); while(true) { if(($newc = socket_accept($socket)) !== false) { echo "Client $newc has connected\n"; $clients[] = $newc; } } ``` 例子2: ``` //服務端腳本,server_socket.php  //創建服務端的socket套接流,net協議為IPv4,protocol協議為TCP $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); /*綁定接收的套接流主機和端口,與客戶端相對應*/ if(socket_bind($socket,'127.0.0.1',8888) == false){ echo 'server bind fail:'.socket_strerror(socket_last_error()); /*這里的127.0.0.1是在本地主機測試,你如果有多臺電腦,可以寫IP地址*/ } //監聽套接流 最大監聽4個套接流 if(socket_listen($socket,4)==false){ echo 'server listen fail:'.socket_strerror(socket_last_error()); } //讓服務器無限獲取客戶端傳過來的信息 do{ /*接收客戶端傳過來的信息*/ $accept_resource = socket_accept($socket); /*socket_accept的作用就是接受socket_bind()所綁定的主機發過來的套接流*/ if($accept_resource !== false){ /*讀取客戶端傳過來的資源,并轉化為字符串*/ $string = socket_read($accept_resource,1024); /*socket_read的作用就是讀出socket_accept()的資源并把它轉化為字符串*/ echo 'server receive is :'.$string.PHP_EOL;//PHP_EOL為php的換行預定義常量 if($string != false){ $return_client = 'server receive is : '.$string.PHP_EOL; /*向socket_accept的套接流寫入信息,也就是回饋信息給socket_bind()所綁定的主機客戶端*/ socket_write($accept_resource,$return_client,strlen($return_client)); /*socket_write的作用是向socket_create的套接流寫入信息,或者向socket_accept的套接流寫入信息*/ }else{ echo 'socket_read is fail'; } /*socket_close的作用是關閉socket_create()或者socket_accept()所建立的套接流*/ socket_close($accept_resource); } }while(true); socket_close($socket); //請注意上面的socket_bind,socket_listen,socket_accept三個函數的執行順序不可更改 //客戶端腳本,client_socket.php //創建一個socket套接流 $socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP); /****************設置socket連接選項,這兩個步驟你可以省略*************/ //接收套接流的最大超時時間1秒,后面是微秒單位超時時間,設置為零,表示不管它 socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, array("sec" => 1, "usec" => 0)); //發送套接流的最大超時時間為6秒 socket_set_option($socket, SOL_SOCKET, SO_SNDTIMEO, array("sec" => 6, "usec" => 0)); /****************設置socket連接選項,這兩個步驟你可以省略*************/ //連接服務端的套接流,這一步就是使客戶端與服務器端的套接流建立聯系 if(socket_connect($socket,'127.0.0.1',8888) == false){ echo 'connect fail massege:'.socket_strerror(socket_last_error()); }else{ $message = 'l love you 我愛你 socket'; //轉為GBK編碼,處理亂碼問題,這要看你的編碼情況而定,每個人的編碼都不同 $message = mb_convert_encoding($message,'GBK','UTF-8'); //向服務端寫入字符串信息 if(socket_write($socket,$message,strlen($message)) == false){ echo 'fail to write'.socket_strerror(socket_last_error()); }else{ echo 'client write success'.PHP_EOL; //讀取服務端返回來的套接流信息 while($callback = socket_read($socket,1024)){ echo 'server return message is:'.PHP_EOL.$callback; } } } socket_close($socket);//工作完畢,關閉套接流 ``` >[danger]為什么PHP socket中的While(true) 不會死循環? 不無限循環就沒法監聽客戶端的連接了。socket和普通web請求不一樣,web請求的監聽是由apache或者nginx這類web服務來監聽的,所以你感覺有始有終,而這類web服務可是一直在運行,就類似于無限循環。 這個socket就有點類似于web服務的意思,一個socket的php可不是由瀏覽器訪問的,而是用命令行啟動一個php進程,擔任web服務器的角色來響應客戶端請求,跟apache之類的web服務就沒關系了,自己就是個服務。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看