使用Winsock的send/ recv时,确认响应是否必要?

问题描述

| 使用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级别!     

解决方法

        您为什么不信任TCP / IP堆栈来保证交付。毕竟,这就是使用TCP而不是UDP的全部重点。     ,这里的现有答案基本上是正确的:如果您使用TCP,那么您实际上不必担心将数据包可靠地传递给对等方。 但这对于必须将数据完整性提升到更高级别的某些系统来说是危险的观点:如果审核日志可能丢失审核条目,则通用标准审核要求“ 0”要求具有防止可审核事件的能力。 (例如,可以将Linux“ 1”审核日志记录守护程序配置为以单用户模式放置计算机,或者在没有更多空间可以容纳审核日志时完全停止系统。)应该保留来自远程系统的审核日志,直到众所周知,它们已成功写入集中式日志服务器。 与简单的TCP相比,最好使用更可靠的协议来处理金融交易-最好使用多阶段协议来处理贷记或借记帐户,以确保资金可用性,执行交易并报告交易结果到起点 TCP允许两个对等点之间(在极端条件下)近1 GB的传输中数据。根据您的应用程序的要求,您可能需要在发送方维护该数据,直到您从同行那里收到有关数据已正确处理的肯定确认。 值得庆幸的是,大多数应用程序并不关键。在此处或那里丢失丢失兆字节数据的套接字报告“将来”某个时刻的连接已关闭确实不可怕,我们只是重试HTTP请求或重新尝试SFTP连接。 更新资料 套接字将仅接受足够的数据以填充其可用窗口。会话握手期间,两个对等方之间协商了窗口大小。因此,当套接字窗口填满时,您对
send()
的调用将开始阻塞。 (操作系统可能还会允许您向其内部缓冲区中添加数据,但是在某些时候,写操作将被阻止。)如果对等方用“ 3”或“ 4”不可达消息断开连接,则将来对“ 2”的调用将返回错误值。连接重置或管道损坏。 更新2   我不是在TCP级别上交谈,而是在Winsock API级别上交谈 这可能是造成混乱的根源。
send()
别无选择,只能在与TCP一起使用时遵守TCP行为。 TCP保证按顺序可靠地传输字节流,以确保可以传输数据包。 (请参阅@Hans关于小马和粗心的人踢电源线的评论。)对等程序将以正确的顺序查看字节。 (嗯,好吧,TCP也有带外紧急数据包传送,但是我实际上没有看到任何使用它的应用程序。使用OOB数据包,您可以脱机获得一些数据。忘了我提到了它) 如果远程程序接收到在TCP流上发送的字节,则它也可靠地接收了所有先前的字节。 (好吧,有一整类重放攻击可以将合法和伪造的数据包拼接在一起供远程对等方使用,但是在具有随机初始序列号的系统上,这些攻击变得越来越困难。如果这在您的威胁模型之内,则应该在顶部使用TLS TCP可以提供加密强度高的篡改明显信息。但是TLS无法提供更好的每数据包传递通知。)     ,        如果您使用UDP,并且您关心的是对方实际接收的数据,则需要使用ACK,但是如果您不需要UDP的速度,则应该使用TCP,因为它会为您进行ACKing。     ,        我认为您已经使这一问题变得复杂了,请相信您的TCP / IP软件堆栈及其提供的可靠交付。 TCP套接字对数据流(而不是数据包)进行操作。同样,打一次
send
并不能保证打一次
recv
。