PHP: проблема прослушивания сокетов - PullRequest
2 голосов
/ 07 апреля 2009

Вот мой код:

<?php

$host = "127.0.0.1";
$portListen = 1234;
$portSend = 1240;


// create socket
$sSender = socket_create(AF_INET, SOCK_STREAM, 0);

socket_connect($sSender, $host, $portListen);

socket_write($sSender, "test", strlen ("test"));


$sListen = socket_create(AF_INET, SOCK_STREAM, 0);
socket_set_option($sListen, SOL_SOCKET, SO_REUSEADDR, 1);

socket_bind($sListen, $host, $portSend);

socket_listen($sListen,1);
$dataSock = socket_accept($sListen);
echo socket_read($dataSock, 3, PHP_NORMAL_READ);

// close sockets
socket_close($sSender);
socket_close($sListen);
?>

Я отправляю "test" в другое приложение, оно получает и отправляет обратно "ack". Проблема в том, что я могу сделать это только один раз. Если я обновлюсь, я получу адрес уже использованной ошибки. Я попробовал решения, предложенные на php.net , но безрезультатно. Попытка socket_shutdown () перед socket_close () выдает только предупреждение о неподключенном подключении, а при обновлении дает бесконечную загрузку.

Из того, что я понимаю, причина, по которой сокет закрывается не сразу, заключается в том, что в буфере все еще есть данные. Но, как вы можете видеть, я четко заявляю, что слушаю только 1 соединение. Кроме того, я отправляю только 3 символа из своего приложения и читаю 3 в этом сценарии.

Что я делаю не так?

edit: причина, по которой я использую 2 сокета, заключается в том, что я не могу слушать () после write (), которая выдает ошибку подключения к сокету. Пропуск listen () и переход к read () после write () приведут к неверной ошибке аргумента.

Ответы [ 3 ]

2 голосов
/ 08 апреля 2009

Я вижу, что после нескольких часов сна и повторного анализа кода и документации мне удалось все исправить. Вы правы, 1 сокета действительно достаточно и правильный путь:

<?php

$host = "127.0.0.1";
$portListen = 1234;
$sSender = socket_create(AF_INET, SOCK_STREAM, 0) or die("Could not create socket\n");

socket_connect($sSender, $host, $portListen) or die("Could not connect\n");

socket_write($sSender, "test", strlen ("test")) or die("Could not write output\n");

echo socket_read($sSender, 3, PHP_NORMAL_READ);

socket_close($sSender);
?>

Так просто!

1 голос
/ 07 апреля 2009

После того, как соединение закрыто, сокет переходит в состояние ожидания, поэтому, если (во время закрытия) пакеты были потеряны и повторно переданы, ответом будет чистое подтверждение вместо RST (сброс), указывающее, что такой сокет не был открыт , Это часть спецификации TCP, вы не можете заставить ее перестать происходить.

Listen(1) не означает принятие только одного соединения, это означает поддержание очереди до 1 соединения, ожидающего, пока приложение accept() их. Поэтому, как только вы примете первое, сокет будет готов к прослушиванию.

Как и всем, мне интересно, почему нечетный дизайн, но я предполагаю, что это сводный пример, который представляет вашу проблему и не обязательно представляет ваш реальный план.

1 голос
/ 07 апреля 2009

Зачем вам нужно создать 2 сокета для чтения и записи? Это выглядит как странный дизайн. Клиентские приложения обычно открывают сокет-соединение с сервером, затем отправляют запрос и читают ответ сервера в том же сокете. Кроме того, создание прослушивающего сокета (iow a server) не будет масштабироваться выше любого брандмауэра или шлюза NAT.

Ответ на комментарий: Не надо слушать. просто прочитайте (возможно, блокирует операцию, если ваш сервер еще не ответил).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...