<?php

if ( !$s = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) ) {
    throw new Exception('socket_create failed: ' . socket_strerror(socket_last_error()) );
}

// $ip = gethostbyname('ya.ru');
$ip = '127.0.0.1';
$port = 8123;
$useNoBlock = in_array('--no-block', $argv);
$isFailtTest = in_array('--fail', $argv);

if ($isFailtTest) {
    $ip = gethostbyname('ya.ru');
    $port = 80;
    echo "Please disconnect LAN after connect\n";
}

echo "Connect to $ip:$port\n";

if ($useNoBlock) {
    socket_set_nonblock($s);
}

if ( !socket_connect($s, $ip, $port) ) {
    if (!canIgnoreError($useNoBlock)) {
        throw new Exception('failed: ' . socket_strerror(socket_last_error()) );
    } else {
        printf("connect: Ignore error %s\n", socket_last_error());
    }
}

while (true) {

    if ($useNoBlock) {
        waitFor($s);
    }

    usleep(100000);

    $data = socket_read($s, 1000);
    if ($data === false) {
        if (!canIgnoreError($useNoBlock)) {
            throw new \Exception("read: " . socket_strerror(socket_last_error()));
        } else {
            echo "read: Ignore error " . socket_last_error() . "\n";
            continue;
        }
    }
    printf("Read %d bytes\n", strlen($data));
    echo "> " . $data . "\n";
}

echo "EOF or error\n";
exit;

function waitFor($s)
{
    $read = [$s];
    $write = [$s];
    $except = [$s];

    echo "Wait ...\n";
    $r = socket_select($read, $write, $except, null);
    assert($r !== false);
    if ($read) {
        echo "Read event\n";
    }
    if ($write) {
        echo "Write event\n";
    }
    if ($except) {
        echo "Except event\n";
    }
}

/**
 * Можно ли игнорировать ошибку вроде SOCKET_EWOULDBLOCK
 */
function canIgnoreError($useNoBlock)
{
    if (!$useNoBlock) {
        return;
    }    

    $e = socket_last_error();
    if (defined('SOCKET_EAGAIN') && $e == SOCKET_EAGAIN) {
        return true;
    }

    return in_array($e, [SOCKET_EWOULDBLOCK, SOCKET_EINPROGRESS]);
}



