2012-03-18 55 views
3

这使我变得疯狂。我必须在php 5.3中创建一个非常简单的非阻塞套接字脚本,客户端使用非阻塞套接字连接到服务器。无法连接到无阻塞的套接字

我试过​​从php manual的例子,但在这两种情况下,当我尝试连接到我得到以下错误的服务器:

socket_connect() [function.socket-connect]: unable to connect [10035]: 
A non-blocking socket operation could not be completed immediately 

我的客户端脚本,错误发生:

$service_port = 2002; 
$address = '127.0.0.1'; 

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
socket_set_nonblock($socket); 
$result = socket_connect($socket, $address, $service_port); 
... 

我使用Zend服务器5.6.0 SP1的免费版本在Win 7

有谁知道如何解决该p或者知道一个简单易懂的非阻塞套接字客户/服务器脚本的例子?

+0

您确定该端口是免费的,并且允许传入和传出数据? – bluegman991 2012-03-18 19:28:27

+0

@ bluegman991是的,我确定该端口是免费的,它允许传入数据,但我不知道如何检查它是否允许传出数据。 – HomeCoder 2012-03-18 19:51:12

回答

9

当你设置你的套接字非阻塞时,你不能指望socket_connect()的结果在连接时返回TRUE,否则返回FALSE。

PHP Manual page

If the socket is non-blocking then this function returns FALSE with an error Operation now in progress.

这是任何语言的真实。你必须设置套接字“阻塞”,或者你必须在你的文件描述符上轮询/选择,然后检查你是否连接正确。 在PHP中,您可能会在一段时间后回想一下socket_connect()函数,以检查它是否返回true,false或等待超时过期。

试试这个代码[EDITED固定在暂停程序的一个小错误]:

<?php 

    $service_port = 2002; 
    $address = '127.0.0.1'; 
    $timeout = 3; 

    $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
    socket_set_nonblock($socket); 
    $error = NULL; 
    $attempts = 0; 
    $timeout *= 1000; // adjust because we sleeping in 1 millisecond increments 
    $connected = FALSE; 
    while (!($connected = @socket_connect($socket, $address, $service_port)) && ($attempts++ < $timeout)) { 
     $error = socket_last_error(); 
     if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { 
       echo "Error Connecting Socket: ".socket_strerror($error) . "\n"; 
       socket_close($socket); 
       return NULL; 
     } 
     usleep(1000); 
    } 

    if (!$connected) { 
     echo "Error Connecting Socket: Connect Timed Out After " . $timeout/1000 . " seconds. ".socket_strerror(socket_last_error()) . "\n"; 
     socket_close($socket); 
     return NULL; 
    } 

?> 
2

以前的解决方案并没有为我工作,所以我发现我的使用socket_select:

<?php 
$service_port = 80; 
$address = '127.0.0.1'; 
$timeout = 3; 

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); 
socket_set_nonblock($socket); 
$error = NULL; 
$attempts = 0; 
$timeout *= 1000; // adjust because we sleeping in 1 millisecond increments 
$connected = FALSE; 
$connected = @socket_connect($socket, $address, $service_port); 
if (!$connected) 
{ 
    $error = socket_last_error(); 
    if ($error != 10035 && $error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) { 
     echo "Error Connecting Socket: ".socket_strerror($error) . "\n"; 
     socket_close($socket); 
     exit(); 
    } 
} 
$writables = array(); 
$writables[] = $socket; 
$readable = array(); 
$e = array(); 
$result = socket_select($readable, $writables, $e, $timeout); 
if (!$result) 
    die("Unable to connect to socket: Timeout"); 
/* blablah send lots of things */ 
socket_close($socket); 

它既可以在Windows上的XAMPP上运行,也可以在我的Linux服务器上运行。

+0

您的代码是迄今为止我发现的唯一一个按预期正常运行的代码。其他代码总是返回“超时”,即使主机明显可连接。 – 2015-03-31 06:50:47