PHP:当客户端在写入时断开连接时,socket_write 挂起

标签 php apache

当我在我的 iOS 应用程序中接收数据时(收到了一些数据,但不是全部)我故意退出该应用程序并且 socket_write 卡在服务器上。相关代码如下:

error_log("start write");
$sent = socket_write($client, $string, $length);
error_log("end write");

我在错误日志中收到了 “开始写入” 消息,但仅此而已,它一直挂起,直到我重新启动 php 程序。

我尝试设置超时,但后来我尝试上传一个大文件,看起来它在上传完成之前就超时了。我认为超时是一段时间不活动,而不是客户端连接的总时间。无论如何,我们将不胜感激。我假设如果套接字断开连接,socket_write 会返回,但要么我错了,要么代码错了。感谢您的帮助。

编辑

基本上,我需要知道客户端何时断开连接。当客户端在写入过程中断开连接并且打开阻塞模式时,看起来 fwrite、socket_send 和 socket_write 都挂起了。如果我关闭阻塞模式,我的代码如下所示:

function send_data($client, $string)
{
    $length = strlen($string);
    socket_set_nonblock($client);
    while(true)
    {
        $sent = socket_write($client, $string, $length);
        //OR - $sent = socket_send($client, $string, $length, 0);

        if($sent === FALSE)
        {
            error_log("false");
            return;
        }
        if($sent < $length)
        {
                $string = substr($string, $sent);
                $length -= $sent;
        }
        else
            return;  
    }
}

问题在于,$sent === FALSE 当客户端断开连接时,而且当它们暂时不可用时,这被证明是在发送前几个字节后发生的,因此不会发送整个字符串。

最佳答案

The problem with this is that, $sent === FALSE when the client disconnects, but also when they are temporarily unavailable, which proved to happen after sending the first few bytes, thus not sending the whole string.

您需要检查 socket_last_error() 是否有 EAGAIN/EWOULDBLOCK

它应该是错误编号 11 或 35,表示套接字仍处于连接状态。

编辑:PHP 包括 constants对于套接字错误。

测试 SOCKET_EWOULDBLOCK。它适用于 Linux 和 Windows。

socket_write definitely does not return after a client disconnect (according to the error log, "start write" shows up, but not "end write" even after waiting for 10 - 30 mins.

如果另一端没有明确关闭连接就消失了,这可能会导致阻塞的 socket_write 调用无限期挂起。

TCP 不会在很长一段时间内自动超时。您可以通过使用非阻塞套接字并测量自上次成功写入以来的时间来强制执行自己的超时。

或者,您可以使用 SO_SNDTIMEO 套接字选项。

关于PHP:当客户端在写入时断开连接时,socket_write 挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30175998/

相关文章:

Apache配置: Websockets Proxy WSS request to WS backend

具有基本身份验证的 Apache 和 Tomcat 反向代理 : Can Tomcat receive the username?

php - 使用 YiiMail 发送密件抄送电子邮件需要很长时间。有办法加快速度吗?

php - 为什么不是对象的所有属性都显示在调试器的变量部分中

php - 为什么 belongsTo() 返回 null?

php - 将一个数组中的元素插入另一个数组的行(每行一个元素)

php - CodeIgniter:实现外部对象(不是模型、 View 或 Controller 的对象)的最佳方式?

php - 如何找到导致 Apache/PHP 常驻内存使用量过高的罪魁祸首模块或脚本?

apache - 无法将/home/pavanbsd/wlsplugin/lib/mod_wl.so 加载到服务器 :/home/pavanbsd/wlsplugin/lib/mod_wl. 所以: undefined symbol :ap_log_rerror

node.js - htaccess Node 应用程序代理