#php #sockets
#php #сокеты
Вопрос:
У меня есть следующий код: http://pastebin.com/U9qYSmET
Когда я пытаюсь подключиться по telnet к своему серверу и порту с
telnet localhost 6667
Я получаю следующую ошибку:
Предупреждение PHP: socket_read(): не удается прочитать из сокета [107]: Конечная точка транспорта не подключена в /var/www/php-irc/proxy.php в строке 91
У кого-нибудь есть какие-либо идеи, почему я получаю эту ошибку?
Код:
<?php
if(!defined('SOCKET_ADDRESS')) {
define('SOCKET_ADDRESS', '127.0.0.1');
}
if(!defined('SOCKET_PORT')) {
define('SOCKET_PORT', '6667');
}
if(!defined('MAX_CLIENTS')) {
define('MAX_CLIENTS', '10');
}
set_time_limit(0);
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($socket, SOCKET_ADDRESS, SOCKET_PORT) or die('Could not bind to address ' . SOCKET_ADDRESS . ' on port ' . SOCKET_PORT . "!n");
socket_listen($socket, MAX_CLIENTS) or die ("Could not setup socket listener!n");
// setup read socket array
$read = array();
// client array w/ default initial socket
$clients = array('0' => array('socket' => $socket));
// force debug at first run..
$debug = true;
$time = time();
printf('Time: %d%s', $time, "n");
while(true) {
if(time() - $time >= 10) {
$time = time();
printf('Time: %d%s', $time, "n");
$debug = true;
}
if($debug === true) {
printf('Debug: %s%s', $debug, "n");
}
// $read[0] = $socket;
if($debug) {
var_dump($read);
}
// Handle clients
for($i = 0; $i < count($clients); $i ) {
if(isset($clients[$i]['socket'])) {
if($debug === true) {
printf('Setting socket %d to client %d%s', $i, $i, "n");
}
$read[$i] = $clients[$i]['socket'];
}
}
if($debug) {
var_dump($read);
}
// Any changed sockets?
// $write and $except are only placeholders
$changed_sockets = socket_select($read, $write = NULL, $except = NULL, 0);
if($debug === true){
printf('Changed sockets: %d%s', $changed_sockets, "n");
}
// Handle new connections
if(in_array($socket, $read)) {
for($i = 0; $i < MAX_CLIENTS; $i ) {
if(!isset($clients[$i])) {
$clients[$i]['socket'] = socket_accept($socket);
socket_getpeername($clients[$i]['socket'],$ip);
$clients[$i]['ip'] = $ip;
printf('Accepting connection into client %d from %s%s', $i, $ip, "n");
break;
}
// } elseif($i == MAX_CLIENTS - 1) {
// echo 'Too many clients connected!', "n";
// }
if($changed_sockets < 1) {
continue;
}
}
}
if($debug) {
var_dump($clients);
}
for($i = 0; $i < count($clients); $i ) {
$client = $clients[$i];
// Has our client socket seen any changes?
if(in_array($client['socket'], $read)) {
printf('Client %d has changed! Reading...%s', $i, "n");
$data = socket_read($client['socket'], 1024);
if($data === false) {
$error = socket_strerror(socket_last_error());
printf('An error occured...%s%s', $error, "n");
}
printf("Read raw data %s from client %i%s", $data, $i, "n");
if($data === null) {
// disconnected
unset($clients[$i]);
}
$data = trim($data);
if($data == 'exit') {
printf('Received exit command from client%s', "n");
socket_close($clients[$i]['socket']);
} elseif($data) {
// Strip whitespace
printf('Received data: %s from client %d%s', $data, $i, "n");
$output = sprintf('%s%s%s', $data, "n", chr(0));
socket_write($client['socket'], $output);
}
}
}
// reset debug
$debug = false;
}
socket_close($socket);
Комментарии:
1. Ваш скрипт действительно запущен? Действительно ли localhost является местом, где запущен сервер?
2. Конечно, он запущен — как еще он мог выдать эту ошибку? И она обязательно должна быть запущена на localhost, иначе telnet пожаловался бы … 😉
3. Туше 😉 Это то, что я получаю за слишком быстрое чтение.
4. Ну что ж, это случается с каждым в какой-то момент. 🙂
Ответ №1:
Вы еще ни к чему не подключились. вам нужно:
socket_connect($socket, $address, $service_port);
в операторе if, чтобы узнать, можете ли вы подключиться.
Комментарии:
1. Хм .. я добавил socket_connect() прямо под socket_listen(). По-прежнему безуспешно.
2. Да. Кроме того, при первом запуске скрипта я получаю эту ошибку сейчас:
PHP Warning: socket_connect(): unable to connect [106]: Transport endpoint is already connected in /home/neen/php-irc/proxy.php on line 20
3. Порт, который вы используете, открыт?
4. Хм. Я так думаю. Странно то, что я могу отправлять данные через telnet, и эти данные записываются обратно в telnet .. независимо от ошибки. Итак, я почти уверен, что порт должен быть открыт. У меня действительно установлены IPtables, но я не думаю, что это что-то блокирует на localhost.
5. Кроме того, сокет, на который я вызываю
socket_read()
, сам прошел через обаsocket_select()
и, позже,socket_accept()
(строки 60 и 68).
Ответ №2:
Проблема заключалась в том, что он пытался прочитать из $clients[0]
. Который не является допустимым клиентом для чтения. Я просто изменил последние два цикла for, чтобы они начинались $i
с 1.
Пока в моем тестировании это, похоже, не оказывает никакого негативного влияния. Ошибка исчезла, и у меня все экземпляры клиента, похоже, работают нормально.