写入数据后向套接字发送错误响应

Posted

技术标签:

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

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

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

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

【问题讨论】:

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

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

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

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

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

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

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

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

    没有响应HEAD 请求;

    没有回复 1xx204304 回复代码;

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

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

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

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

【讨论】:

以上是关于写入数据后向套接字发送错误响应的主要内容,如果未能解决你的问题,请参考以下文章

C++ Winsock 套接字错误:10038 (WSAENOTSOCK)

通过写入 DataOutputStream 通过蓝牙向设备发送命令

对于 UDP 套接字,发送函数不会失败,但写入的数据仍然比请求的少吗?

如何使用非阻塞套接字正确处理发送/写入?

***Error 然后 SocketException:软件导致连接中止:套接字写入错误 [重复]

java.net.SocketException:软件导致连接中止:套接字写入错误[重复]