Unable to connect to a non-blocking socket

筅森魡賤 提交于 2019-12-07 16:44:31

问题


This makes me nuts. I have to create a very simple non-blocking socket script in php 5.3 where a client connects to a server, both using non-blocking sockets.

I've tried phpsocketdaemon and the example from the php manual, but in both cases when I try to connect to the server I get the following error:

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

My client script where the error happens:

$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);
...

I'm using the free version of Zend Server 5.6.0 SP1 on Win 7.

Does anyone know how to fix this problem or know a simple and understandable example of a non-blocking socket client/server script?


回答1:


When you set your socket non blocking you cannot expect that the result of socket_connect() returns TRUE if it's connected or FALSE if not.

PHP Manual page:

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

This is true in any language. You have to set the socket "blocking" or you have to poll/select on your file descriptor before checking if you are correctly connected or not. In PHP you may recall the socket_connect() function after a small period of time to check if it returns true, false or wait for timeout to expire.

Try this code [EDITED to fix a small error on timeout routine]:

<?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:


Previous solution didn't worked for me, so I found mine using 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);

It's working both on XAMPP on windows and on my linux server.



来源:https://stackoverflow.com/questions/9761472/unable-to-connect-to-a-non-blocking-socket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!