【问题标题】:Writing to a socket and handling broken pipes写入套接字并处理损坏的管道
【发布时间】:2011-11-04 18:36:37
【问题描述】:

我在 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);
}

【问题讨论】:

    标签: php sockets broken-pipe


    【解决方案1】:

    第一季度。我想知道需要什么(最安全的方法)才能从中恢复。

    答:这取决于应用程序。套接字侦听器正在关闭连接,或者您设置了未向我们显示的套接字选项。您如何处理这些事情取决于应用程序的语义。

    第二季度。我还想知道 socket_write 是否可以在不写入传递给它的完整字符串的情况下返回。

    答:是的。 socket_write() 可以在返回之前不写入任何字节、部分字节或所有字节。如果它返回一个大于零但小于输入长度的值,您应该调整偏移量(可能使用substr())。如果它返回零或更少,请检查socket_last_error() 以获取有关它是否可重试的线索。这种扭曲被覆盖in the manual

    【讨论】:

    • 我传入的唯一选项是我在示例中的选项。有人告诉我,我不必担心 socket_write 写的字符比指示的少,因为这是一个 UNIX 域套接字,所以没有网络延迟。你同意吗?
    • socket_write() 的文档没有提供这样的保证。
    【解决方案2】:

    您是否尝试过设置 SO_KEEPALIVE 或 SO_SNDTIMEO?您还可以在循环中测试缓冲区长度,以查看整个内容是否已发送。

    祝你好运,HTH, -- 乔

    【讨论】:

    • 我知道我可以测试 socket_write 的返回值以查看实际写入了多少字节,我的问题是这是否真的有必要,我见过的大多数示例都没有尝试这样做。另外,通过设置 SO_KEEPALIVE 和 SO_SNDTIMEO 我不会得到损坏的管道是什么意思?管道损坏是因为套接字服务器(不是 PHP)有问题。我认为我无法在 PHP 客户端上做任何事情来防止这种情况发生。
    • 警告消息:检测到错误,阻止了此页面的加载。如果此问题仍然存在,请联系网站管理员。 socket_write() [function.socket-write]: 无法写入套接字 [32]: Broken pipe application/classes/cci/DataSrv.php
    【解决方案3】:

    使用socket_set_nonblock() 并修复您的while 语句:

    $writeResult === FALSE 应改为 $writeResult !== FALSE

    【讨论】:

    • 为什么要使用socket_set_nonblock?在读取套接字之前,脚本无需执行任何其他操作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-12
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 2010-12-25
    相关资源
    最近更新 更多