Я хочу отправить данные через сокет на 2 разных конечных точки. Это для отправки сообщений через WebSockets и Push-Services (отдельный рабочий экземпляр делает это).
Поскольку моему приложению не требуется ответ от конечной точки, я установил неблокирование сокета, чтобы мои приложения быстро завершали запрос.
Проблема в том, что выполняется только последний socket_write. Первая конечная точка не получает данные.
Вот код:
foreach ($workerInstances as $workerInstance) {
// $workerInstance contains a hostname
$sock=socket_create(AF_INET, SOCK_STREAM,SOL_TCP);
socket_set_nonblock($sock);
$connRes = socket_connect($sock, $workerInstance, 8018);
if ($connRes) {
$written = socket_write($sock, $data,strlen($data));
socket_close($sock);
if ($written === FALSE) {
$result[] = $workerInstance . ': Connected but failed to write';
++$failures;
} else {
$result[] = $workerInstance . ': OK - ' . $written . ' bytes written';
}
} else {
++$failures;
$result[]=$workerInstance . ': Failed';
}
}
$ результат тогда:
[
"app01.local: Connected but failed to write",
"app02.local: OK - 63 bytes written"]
Я думаю, что возвращение socket_write в неблокирующем режиме не является надежным, верно? Но первая конечная точка действительно не получает данных. В режиме блокировки обе конечные точки получают свои данные.
Что я делаю неправильно?
Нашел решение на http://php.net/manual/en/function.socket-connect.php#84465
В неблокирующем режиме мне нужно дождаться завершения подключения к сокету, прежде чем записывать в сокет. Поэтому мы выполняем соединение в цикле до тех пор, пока результат не станет ЛОЖНЫМ или пока ошибка не будет отлична от «Соединение в процессе» (или мы подождали достаточно долго, чтобы установить соединение).
foreach ($workerInstances as $workerInstance) {
$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_nonblock($sock);
// wait until connection established
$attempts = 30;
while (!($connRes = socket_connect($sock, $workerInstance,
8018)) && $attempts) {
$error = socket_last_error();
if ($error != SOCKET_EINPROGRESS && $error != SOCKET_EALREADY) {
$result[] = $workerInstance . ' Socket connect error: ' . socket_strerror($error);
break;
} else {
$result[] = $workerInstance . ' Connecting...';
}
usleep(1000);
--$attempts;
}if ($connRes) {
$written = socket_write($sock, $data,strlen($data));
if ($written === FALSE) {
$result[] = $workerInstance . ': Connected but failed to write';
++$failures;
} else {
$result[] = $workerInstance . ': OK - ' . $written . ' bytes written';
}
} elseif ($attempts === 0) {
++$failures;
$result[]=$workerInstance . ': Failed - Timeout!';
} else {
++$failures;
$result[]=$workerInstance . ': Failed';
}
socket_close($sock);
}
Теперь результат $
[
"app01.local Connecting...",
"app01.local: OK - 63 bytes written",
"app02.local Connecting...",
"app02.local: OK - 63 bytes written",
]
Других решений пока нет …