Запись в розетку и обработка сломанных труб - PullRequest
8 голосов
/ 26 августа 2011

У меня есть некоторый код в PHP, который подключается к сокету. Я периодически получаю сломанную трубу, когда пишу ей. Проблемы, похоже, исчезнут, если снова написать в трубу. Мне интересно, что требуется (самый безопасный способ), чтобы оправиться от него. Мне также интересно, может ли socket_write возвращаться без записи полной строки, которая была передана в него. Вот что у меня сейчас.

function getSocket() {
  $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
  if ( $socket === FALSE ) {
    throw new Exception(
      "socket_create failed: reason: " . socket_strerror( socket_last_error() ));
    }
  }

  $result = socket_connect($socket, $address);
  if ($result === false) {
    throw new Exception("socket_connect() failed.\nReason: ($result) " .
        socket_strerror(socket_last_error($socket)));
  }
  return $socket;
}

function writeSocket($stmt) {
  $tries = 0;
  $socket = getSocket();
  do {
    // Is is possible that socket_write may not write the full $stmt?
    // Do I need to keep rewriting until it's finished?
    $writeResult = socket_write( $socket, $stmt, strlen( $stmt ) );
    if ($writeResult === FALSE) {
      // Got  a broken pipe, What's the best way to re-establish and 
      // try to write again, do I need to call socket_shutdown?
      socket_close($socket);
      $socket = getSocket();
    }
    $tries++;
  } while ( $tries < MAX_SOCKET_TRIES && $writeResult ===  FALSE);
}

Ответы [ 3 ]

2 голосов
/ 27 августа 2011

Q1.Мне интересно, что требуется (самый безопасный способ) для восстановления после него.

A: Это зависит от приложения.Слушатель сокета закрывает соединение, или вы установили параметры сокета, которые вы нам не показываете.То, как вы справляетесь с любой из этих вещей, зависит от семантики приложения.

Q2.Мне также интересно, может ли socket_write возвращаться без записи полной строки, которая была передана в него.

A: Да.socket_write() не может записать байты, некоторые байты или все байты перед возвратом.Если он возвращает значение больше нуля, но меньше длины входа, вы должны отрегулировать смещения (возможно, используя substr()).Если он возвращает ноль или меньше, проверьте socket_last_error() на наличие подсказок, можно ли повторить попытку.Это искажение рассматривается в руководстве .

0 голосов
/ 27 августа 2011

Используйте socket_set_nonblock() и исправьте while утверждение:

$writeResult === FALSE должно быть $writeResult !== FALSE вместо.

0 голосов
/ 26 августа 2011

Вы пытались установить SO_KEEPALIVE или SO_SNDTIMEO?Вы также можете проверить в цикле длину буфера, чтобы убедиться, что все это было отправлено.

Удачи и HTH, - Джо

...