配置套接字ACK超时? - c#

有没有一种方法可以配置超时时间,即套接字在确定连接失败之前希望收到发送数据的ACK?

我知道也可以在应用程序级别完成此操作,但是由于我发送的每个数据包始终都会被确认,因此我只想知道是否接收到我的数据,因此可以在应用程序级别使用其他数据来完成相同的操作事情似乎很浪费。 (更不用说,我的特定应用程序使用按字节收费的蜂窝链接。)

注意:根据我之前的问题-
What conditions cause NetworkStream.Write to block?-您不能依靠.Write引发异常来确定数据发送不正确。

参考方案

这是一个古老的问题,但它引起了我的注意...正如您原始问题中提到的那样,这应该在应用程序层完成。

我希望我的经验可能会有所帮助,因为我的想法与您完全一样(甚至坚持认为TCP应该完成工作,甚至与我团队中的其他开发人员进行了战斗)。实际上,将TCP与无线连接,冲突的网络MTU以及有时实施不当的路由器/接入点(会过早地或在故障条件下进行确认)的混乱搞混非常容易。但这也是因为TCP旨在从一个源流向一个目的地,而不是真正确保全双工事务通信。

我为嵌入式设备制造商工作了数年,并为仓库中的无线条形码终端编写了完整的客户端-服务器系统。在这种情况下,不是蜂窝网络,但是wifi可能同样糟糕(但即使是wifi也会证明所需的任务没有用)。仅供参考,我的系统在将近7年后的今天仍可在生产中可靠地运行,因此我认为我的实施相当可靠(工业制造机器/焊接机/空气压缩机/小鼠咀嚼网线等经常受到干扰)。

了解问题

@rodolk发布了一些不错的信息。 TCP级别的ACK不一定与您的每个应用程序网络传输都对应1-1(并且,即使您禁用了Nagle,如果发送的数据量超过网络的MTU或最大数据包大小,则TCP ACK也不总是1-1)。

IP Datagram Size, the Maximum Transmission Unit (MTU), and Fragmentation Overview
Dealing with Fragmented Traffic
Wireless Networking MTU - Physical MTU vs Logical Packet Size

最终,TCP和IP(Transport and Network layers)的机制是确保在一个方向(从源到目的地)上传递流量,并限制最大重试次数等。应用程序通信最终涉及位于TCP / IP之上的全双工(双向)Application layer通信。混合这些层不是一个好的策略。考虑一下TCP / IP之上的HTTP请求-响应。 HTTP不依靠TCP ACKS来实现自己的超时,等等。如果您感兴趣的话,HTTP将是一个不错的选择。

但是,我们甚至假装它正在执行您想要的操作。您总是在1次传输中发送少于1个MTU(或最大数据包大小)的数据,并且恰好收到1个ACK。介绍您的无线环境,一切都会变得更加复杂。在成功传输和相应的ACK之间可能会出现故障!

问题在于无线通信流的每个方向不一定具有相同的质量或可靠性,并且会根据本地环境因素和无线设备的移动而随时间变化。

设备接收的信号通常比传输的信号好。设备通常会完美地接收您的传输,并以传输的某种“ ACK”进行回复,但是由于信号质量,传输距离,RF干扰,信号衰减,信号反射等原因,无线ACK永远无法到达目的地。在工业应用中,可能是重型机械开启,焊接机,冰箱/冰柜,荧光灯等,在城市环境中可能是建筑物,停车场,钢结构等内部的移动性。

在这种情况下,客户端什么时候采取措施(保存/提交数据或更改状态),服务器什么时候认为该措施成功(保存/提交数据或更改状态)?如果没有在应用程序层中进行额外的通信检查,这将很难可靠地解决(有时包括用于事务的2路ACK,即:客户端传输,服务器ACKS,客户端ACK ACK :-)此处不应依赖TCP级别ACK,因为它们将不会可靠地等同于成功的全双工通信,也不会为您的应用程序提供可靠的重试机制。

嵌入式设备上不可靠无线通信的应用层技术

我们的技术是,每个应用程序级别的消息均以一对字节的应用程序级别报头发送,该报头包括一个数据包ID#(只是一个递增整数),整个消息的长度(以字节为单位)和整个消息的CRC32校验和。我不记得了,但是我相信我们用8个字节[2 | 2 | 4.(取决于您要支持的最大邮件长度)。

因此,假设您要计算仓库中的库存,计算一个项目并计算5个单位,条形码终端会向服务器发送一条消息,说“本计算了1234个项目的5个单位”。服务器收到消息后,将等待直到收到完整的消息,首先验证消息的长度,然后验证CRC32校验和(如果长度匹配)。如果所有这些都通过,我们将向应用程序发送对此消息的响应(类似于应用程序的ACK)。在这段时间内,条形码终端正在等待来自服务器的ACK,如果没有收到来自服务器的回音,它将重新发送。如果服务器收到同一数据包ID的多个副本,则可以通过放弃未提交的事务来进行重复数据删除。但是,如果条形码扫描仪确实从服务器接收到其ACK,则它将再向服务器发送最后一个“ COMMIT”命令。由于前2条消息刚刚验证了工作的全双工连接,因此提交在这几毫秒的时间内不太可能失败。仅供参考,这种故障状况很容易在WiFi覆盖范围的边缘复制,因此带上笔记本电脑/设备散步直到wifi仅为“ 1 bar”或最低连接速度(通常为1 mbps)。

因此,您要在消息的开头添加8个字节的标头,如果在无线通信的仅一侧可能失败时需要事务处理的请求/响应,则可以选择添加一个额外的最终COMMIT消息传输。

很难证明使用复杂的应用程序层将每个消息节省8个字节来传输层连接系统(例如,连接到winpcap)。另外,您是否可以复制挂接到其他设备上的传输层(也许您的系统将来会在其他设备上运行?Android,iOS,Windows Phone,Linux,您可以为所有这些实现相同的应用程序层通信吗?平台吗?我认为无论TCP堆栈如何实现,您都应该能够在每个设备上实现应用程序。)

我建议您将应用程序层与传输层和网络层分开,以实现关注点的良好分离,并严格控制重试条件,超时和可能发生的应用程序状态更改。

获取家庭路由器上的客户端MAC地址列表 - python

                                                                                                                    我正在为自己建立一个小项目,遇到一个小问题。我有一个wifi路由器,可以通过键入192.168.0.1然后进入浏览器连接到该路由…

LeetCode题解计算机为什么是基于二进制的?

可以是三进制么?二进制有什么好处?题解:为什么叫电子计算机?算盘应该没有二进制

LeetCode题解统计城市的所有灯泡

这个是我刚毕业的时候,一个真实的面试题,这是一个开放题。题目描述:想办法,将一个城市的所有灯泡数量统计出来。题解:费米估算法1、如果某个城市常驻人口有1000万2、假设每5人居住在一套房里,每套房有灯泡5只,那么住宅灯泡共有1000万只3、假设公众场所每10人共享一只灯泡,那么共有100万只4、主要的这两者相加就得出了1100万只当然实际上这是估算的,具体应…

LeetCode题解黑白圆盘

一个圆盘被涂上了黑白二色,两种颜色各占一个半圆。圆盘以一个未知的速度、按一个未知的方向旋转。你有一种特殊的相机可以让你即时观察到圆上的一个点的颜色。你需要多少个相机才能确定圆盘旋转的方向?题解:可以用一个相机即可

LeetCode题解圆上任取三点构成锐角三角形的概率

来自字节跳动的一道几何题题解:1/4