【问题标题】:Sending error response to socket after data has been writen写入数据后向套接字发送错误响应
【发布时间】:2016-06-06 06:26:49
【问题描述】:

我有一个使用 c 编写 HTTP 服务器的任务。服务器读取请求并相应地发送响应。当请求是文件的路径时,我需要读取文件内容并将其作为响应发送给客户端。

文件大小没有限制,所以我按块读取它并按块发送响应。老师说如果recv/send调用在已经写完部分响应后失败,可以关闭连接并继续,但是应该通知客户端响应没有正确发送。

我的问题是,假设发送调用失败,尝试发送响应未正确发送的消息可能会再次失败。我如何通知客户发送响应时出错?

【问题讨论】:

  • 也要看失败的原因,如果是连接丢失了就不能通知客户端了。
  • http header 通常包含文件大小。所以客户端可以推断它没有收到所有东西。

标签: c sockets


【解决方案1】:

您的老师并不是说您的服务器应该通知客户端,而是应该(已经)通过recv() 通知客户端,因此,除了关闭连接之外,您在服务器端不需要做任何特别的事情.

1也就是说,假设你的老师没有困惑。

【讨论】:

    【解决方案2】:

    您老师的陈述与所述不符,或含糊不清。 HTTP 状态代码位于有效负载之前。如果写入有效负载时出错,除了重置连接,如果您知道如何执行此操作,或者如果(很可能)由于发送错误而已经发生,则无法通知对等方。

    【讨论】:

      【解决方案3】:

      老师说如果recv/send调用在已经写完部分响应后失败,可以关闭连接继续,但是应该通知客户端响应没有正确发送。

      首先,一旦您开始send() 回复,您不应该调用recv(),直到回复完整发送。在当前响应完成之前,您不能开始recv()'ing 下一个请求。

      其次,如果recv()send()因任何原因失败,您必须关闭当前连接,没有其他选择。

      我的问题是,假设发送调用失败,尝试发送响应未正确发送的消息可能会再次失败。否则如何通知客户端发送响应时出错?

      您不能,也不应该尝试这样做。如果这是您的老师告诉您的,那么您可能误解了老师的实际意思,或者您的老师不了解 HTTP 的实际工作原理。

      当连接失败时,关闭连接是唯一的选择。如果客户端还没有失败,它将(最终)检测到关闭(或超时),并且由于没有完整收到响应这一事实而知道响应失败。它如何检测响应的结束取决于响应的格式(有关详细信息,请参阅RFC 2616 Section 4.4 Message Length)。

      请注意 - 存在一种情况,即连接关闭并不表示响应失败!如果服务器:

      1. 没有响应HEAD 请求;

      2. 没有回复 1xx204304 回复代码;

      3. 未发送Content-LengthTransfer-Encoding: identity 响应标头;

      4. 没有以multipart/byteranges 格式发送响应正文;

      然后服务器关闭连接优雅地完成响应(服务器使用shutdown(SD_SEND)shutdown(SD_BOTH)有意关闭,它发送一个启用FIN标志的TCP数据包. 在某些平台上,包括 Windows,close()/closesocket() 会执行隐式关闭,但最好是显式的。

      客户端必须查看响应标头以检测响应的发送方式并采取相应措施。如果它属于最后一个条件,则只有 graceful 断开连接被视为成功。任何其他类型的断开都将被视为失败。因此,服务器至少应始终发送Content-LengthTransfer-Encoding 标头。它避免了断开连接所代表的模糊性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-11-29
        • 2018-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多