jjzjj

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

coder 2024-04-17 原文

当我在我的 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/

有关PHP:当客户端在写入时断开连接时,socket_write 挂起的更多相关文章

  1. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  2. ruby - attr_accessor 在写入时将 nil 转换为字符串 - 2

    我有一个数据对象,其中包含许多用于各种输入的attr_accessor字段。我可以以某种方式定义类,以便所有字段的所有setter都将例如将值设置为空字符串而不是尝试的nil? 最佳答案 这里有一个小模块可以做到这一点:moduleNilToBlankAttrAccessordefnil_to_blank_attr_accessor(attr)attr_readerattrdefine_method"#{attr}="do|value|value=''ifvalue.nil?instance_variable_set"@#{attr

  3. ruby - 在 TCPServer (Ruby) 中,我如何从客户端获取 IP/MAC? - 2

    我想在Ruby的TCPServer中获取客户端的IP地址。以及(如果可能的话)MAC地址。例如,Ruby中的时间服务器,请参阅评论。tcpserver=TCPServer.new("",80)iftcpserverputs"Listening"loopdosocket=tcpserver.acceptifsocketThread.newdoputs"Connectedfrom"+#HERE!HowcanigettheIPAddressfromtheclient?socket.write(Time.now.to_s)socket.closeendendendend非常感谢!

  4. ruby-on-rails - 什么会导致与 APNS 的连接间歇性断开连接? - 2

    我有一个ruby​​脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?

  5. ruby - 如何断开现有的 ruby​​ 续集与数据库的连接? - 2

    我的意思是之前建立的那个DB=Sequel.sqlite('my_blog.db')或DB=Sequel.connect('postgres://user:password@localhost/my_db')或DB=Sequel.postgres('my_db',:user=>'user',:password=>'password',:host=>'localhost')等等。Sequel::Database类没有名为“disconnect”的公共(public)实例方法,尽管它有一个“connect”。也许有人已经遇到过这个问题。我将不胜感激。 最佳答案

  6. ruby-on-rails - 这个 C 和 PHP 程序员如何学习 Ruby 和 Rails? - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我来自C、php和bash背景,很容易学习,因为它们都有相同的C结构,我可以将其与我已经知道的联系起来。然后2年前我学了Python并且学得很好,Python对我来说比Ruby更容易学。然后从去年开始,我一直在尝试学习Ruby,然后是Rails,我承认,直到现在我还是学不会,讽刺的是那些打着简单易学的烙印,但是对于我这样一个老练的程序员来说,我只是无法将它

  7. ruby-on-rails - 为什么我必须在使用客户验证器后重新加载 rspec 中的记录? - 2

    我有一个模型User,它在创建后的回调中创建了选项#Userhas_one:user_optionsafter_create:create_optionsprivatedefcreate_optionsUserOptions.create(user:self)end我对此有一些简单的Rspec覆盖:describe"newuser"doit"createsuser_optionsaftertheuseriscreated"douser=create(:user)user.user_options.shouldbe_kind_of(UserOptions)endend一切正常,直到我将自

  8. ruby - 如何获得带有 SSL 客户端证书的 HTTPS 请求以与 Ruby EventMachine 一起使用? - 2

    我正在尝试使用RubyEventMachine访问使用SSL证书身份验证的HTTPSWeb服务,但我没有让它工作。我编写了以下简单代码块来对其进行端到端测试:require'rubygems'require'em-http'EventMachine.rundourl='https://foobar.com/'ssl_opts={:private_key_file=>'/tmp/private.key',:cert_chain_file=>'/tmp/ca.pem',:verify_peer=>false}http=EventMachine::HttpRequest.new(url).g

  9. ruby-on-rails - 在 Ruby on Rails 应用程序中使用客户端 SSL - 2

    我正在为需要与API建立SSL连接的客户端开发应用程序。我得到了三个文件;一个信任根证书(.cer)文件、一个中间证书(.cer)文件和一个签名的响应文件。我得到的安装说明与IIS或Javakeytool程序有关;我正在用RubyonRails构建应用程序,所以这两种方法都不是一个选项(据我所知)。证书由运行API服务的组织自签名,看来我获得了客户端证书以相互验证https连接。我不确定如何使用我的应用程序中的证书连接和使用API签名响应文件的作用我读过"Usingaself-signedcertificate"和thisarticleonOpenSSLinRuby但两者似乎都不是很到

  10. ruby - 为什么这个启用 SSL 的 Ruby 服务器/客户端测试有效? - 2

    我正在努力在Ruby中创建启用SSL的服务器,以及与服务器一起使用的相应Ruby客户端。为了进行测试,我使用以下命令创建了自己的根CA证书。$:~/devel/ssl-test/ssl/CA$opensslgenrsa-outTestCA.key2048GeneratingRSAprivatekey,2048bitlongmodulus............+++...........................+++eis65537(0x10001)$:~/devel/ssl-test/ssl/CA$opensslreq-new-keyTestCA.key-outTestCA.

随机推荐