写入数据后向套接字发送错误响应
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
请求;
没有回复 1xx
、204
或 304
回复代码;
未发送Content-Length
或Transfer-Encoding: identity
响应标头;
没有以multipart/byteranges
格式发送响应正文;
然后服务器关闭连接优雅地完成响应(服务器使用shutdown(SD_SEND)
或shutdown(SD_BOTH)
有意关闭,它发送一个启用FIN
标志的TCP数据包. 在某些平台上,包括 Windows,close()
/closesocket()
会执行隐式关闭,但最好是显式的。
客户端必须查看响应标头以检测响应的发送方式并采取相应措施。如果它属于最后一个条件,则只有 graceful 断开连接被视为成功。任何其他类型的断开都将被视为失败。因此,服务器至少应始终发送Content-Length
或Transfer-Encoding
标头。它避免了断开连接所代表的模糊性。
【讨论】:
以上是关于写入数据后向套接字发送错误响应的主要内容,如果未能解决你的问题,请参考以下文章
C++ Winsock 套接字错误:10038 (WSAENOTSOCK)
通过写入 DataOutputStream 通过蓝牙向设备发送命令
对于 UDP 套接字,发送函数不会失败,但写入的数据仍然比请求的少吗?