使用 Winsock、C++,我使用send()/recv()和 TCP 连接发送和接收数据。我想确定数据是否已经传递给对方,并且想知道是否建议在(如果)使用recv接收数据之后发回一些确认消息。
这里有两种可能性,请建议走哪条路:
如果send返回传递缓冲区的大小,则假定数据至少已传递到线路另一端的recv函数。当我说“至少”时,我的意思是即使recv在那里失败(例如由于缓冲区不足等),我不在乎,我只是想确保我已经正确完成了我的服务器部分工作 -我已经完全发送了数据(即数据到达了另一台机器)。
使用附加确认:在使用recv接收到数据后,发回接收到的数据包的一些 ID(发送的每个数据的标头的一部分),表明该数据包的成功接收操作。如果在一段时间后我没有收到这样的“确认消息”,请从发件人函数返回失败代码。
第二个答案看起来更安全,但如果它是多余的,我不想使传输协议复杂化。另请注意,我说的是 TCP 连接(它本身比 UDP 更安全)。
是否有任何其他机制(可能是其他一些 API?也许WSARecv()/WSASend()工作方式不同?)确保数据被传递到另一端的recv函数?
如果您推荐第二种方式,您能否给我一些代码片段,让我可以使用带有超时的recv来接收确认?recv是一个阻塞操作,因此如果之前的发送尝试失败(未通知对方),它将永远挂起。是否有任何简单的方法可以使用带有超时的recv(无需每次都创建单独的线程,这可能是每个发送操作的过度杀伤力)。
此外,我传递给发送函数的数据量可能非常大(几兆字节),那么如何选择“确认消息”的超时时间?也许我应该“拆分”大缓冲区并使用多个发送调用?我觉得会很复杂,请指教!
编辑:好的,你们建议 TCP/IP 堆栈将处理它(即不需要手动确认),但这是我在 MSDN 页面上找到的:“发送功能的成功完成并不表示数据成功发送和接收到收件人。此功能仅表示数据已成功发送。因此,即使 TCP 机制有能力确保数据传递,我也无法通过send()函数或我知道的任何其他 Winsock 函数获得该状态(成功与否)。您知道从 TCP 层获取状态的任何方法吗?再次 - send()函数的返回值似乎还不够!
==================================================== ======
编辑 2:好的,我认为我们同意即使 TCP 协议在出现问题时考虑错误处理,Winsock 的send()函数也无法报告错误(仅仅是因为它在实际数据传输开始之前返回网络驱动程序)。所以这里有一个百万美元的问题:Winsock 的send()函数是否至少确保在当前数据包发送之前不会有其他数据包被传递给对方?换句话说,如果由于某些网络故障(但没有通过send()调用报告)发送失败,那么网络故障将在下一次调用send()函数和下一个数据块之前修复,是否可以确保前一个数据包(失败但未报告send() ) 将在下一个数据包之前交付吗?换句话说,一个特定的 send() 函数是否有可能“静默”失败,以便后续的 send() 调用会成功但第一个数据包会丢失?再次 - 我不是在说 TCP 级别,我说的是 Winsock API 级别!