2013-11-01 38 views
0

我有一個運行Apache 2.2.3和PHP 5.4.8的CentOS 5.9框。通過apache運行stream_socket_server&client時連接被拒絕

我試圖設置一個使用PHP的服務器,以便另一臺服務器上的C應用程序可以輕鬆地從我們的Web服務器上查詢一些信息。

我也希望能夠在本地向服務器發送數據包 - 從同一個網絡服務器 - 方便地控制服務器。

問題是,當服務器和客戶端都通過瀏覽器/ apache訪問時,客戶端從未設法連接。當我通過CLI執行客戶端或服務器時,它突然生效。

我在Ubuntu工具箱上測試了相同的代碼,它沒有任何問題。

對於測試/調試,服務器在30秒後自動關閉。

澄清:


  • 瀏覽器去serverstart.php
  • 瀏覽器去client.php
  • 結果:client.php保持加載,直到serverstart.php命中30秒關機,然後迴應連接拒絕

  • 瀏覽器轉到serverstart2.php,它使用exec,passthru或system('php -f serverstart.php');
  • 瀏覽器轉到client.php
  • 結果:不起作用。客戶端掛起,直到serverstart.php在30秒後關閉。

  • CLI:PHP -f serverstart.php
  • 瀏覽器去client.php
  • 結果:工作

  • 瀏覽器去serverstart。 php
  • CLI:PHP -f client.php
  • 結果:工作

  • 瀏覽器去serverstart.php
  • CLI:回聲 「測試」 |數控本地主機8000
  • 結果:工作

客戶端。PHP

<?php 

$client = stream_socket_client("tcp://localhost:8000", $errno, $errorMessage); 

if ($client === false) { 
    echo "Failed to connect: $errorMessage"; 
} 

fwrite($client, "This is a test" . PHP_EOL); 
echo stream_get_contents($client); 
fclose($client); 

serverstart.php

<?PHP 
$server = stream_socket_server("tcp://0.0.0.0:8000", $errno, $errorMessage); 

if ($server === false) { 
    throw new UnexpectedValueException("Could not bind to socket: $errorMessage"); 
} 

$start = microtime(true); 

while((microtime(true) - $start) < 30) { // 30 second timeout 
    $client = @stream_socket_accept($server, 1); 

    if ($client) { 
     echo 'Client Found'; 
     $message = fgets($client, 1024); 
     echo 'Client said:' . $message; 
     fwrite($client, 'The local time is ' . date('n/j/Y g:i a') . PHP_EOL); 
     fclose($client); 
    } 
} 

任何人有任何想法什麼怎麼回事,我怎麼能得到它的工作,通過瀏覽器調用兩者兼而有之?

編輯:我想補充說,沒有防火牆正在運行的框。 iptables空白,SELinux被禁用。

回答

0

確切地說是延遲迴答,但不知道您的apache和php配置,或者您的Ubuntu和CentOS配置之間的差異。我相信權限可能是您問題的根源。

例如,當您通過CLI運行腳本並使用su apache; php serverstart.php;時,您應該得到與從瀏覽器運行時相同的結果。與以root身份運行CLI相反。這是由於apache沒有權限連接指定的ip/port。

此外,確保您的端口8000未被Apache(或其他服務)使用,因爲它是許多配置中的通用端口,並且可能在嘗試通過php訪問時被阻塞。通常在你的Apache配置中的某處,它將包含Listen *:8000或類似的東西。

EG:http://localhost:8000 -> Apache -> php -> fsockopen('tcp://localhost:8000')(已在使用中),PHP超時,端口打開,然後client.php響應連接拒絕。

您可以通過創建一個只包含<?php sleep(120);的腳本(test.php)來檢查衝突,然後在test.php處於睡眠狀態時從CLI執行servertstart.php。

同樣在您的serverstart.php中,請務必在腳本末尾執行fclose($server);stream_socket_shutdown($server, STREAM_SHUT_RDWR);以確保服務器不會處於不可用狀態。此外,至少要添加一個usleep(500)以防止額外的CPU使用。如果stream_socket_accept返回false,則應該退出循環,因爲它指示發生了錯誤,而不是從循環內調用@stream_socket_accept

while($timer < 30 && ($client = stream_socket_accept($server, 1))){ 
    $timer = (microtime(true) - $start); 
    //code here 
} 

如果上述不幫助我認爲正在發生的是默認的Apache Web服務器充當PHP的包裝和使用Apache的用戶和組權限執行。這就是爲什麼你的web文件通常具有用戶組apache權限,目錄上有750個,文件上有640個。 這允許Apache訪問虛擬主機目錄中的目錄和文件,並拒絕匿名訪問,然後當它讀取PHP文件時,apache執行php並將結果輸出爲text/html。 但是Apache無法訪問其他系統資源

您可以通過在一個腳本內執行echo exec('whoami');並從瀏覽器導航到其中來檢查正在運行的用戶。

權限問題有幾種解決方法,其中大多數是不好的做法,並會在服務器上出現安全漏洞。

您可以在連接之前通過在serverstart.php和client.php中執行umask(0);來解決問題。這意味着創建的任何內容都將使用0777權限,包括套接字。或者,您可以嘗試在serverstart.php和client.php上設置chmod(755),以查看是否允許匿名用戶對文件執行權限來解決問題。

否則,您可以考慮爲您的Web服務創建一個包裝,例如suexecphp-fpm,並通過Apache作爲用戶名/用戶組和適當的umask設置執行fastcgi。然後確保您的用戶有權在指定的IP /端口上打開連接。