Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 配置套接字确认超时?_C#_Sockets_Network Programming_Tcpclient - Fatal编程技术网

C# 配置套接字确认超时?

C# 配置套接字确认超时?,c#,sockets,network-programming,tcpclient,C#,Sockets,Network Programming,Tcpclient,是否有一种方法可以配置套接字在确定连接失败之前接收已发送数据的ACK的超时时间 我知道这也可以在应用程序级别上完成,但由于我发送的每个数据包都是经过确认的,我只想知道是否收到了我的数据,因此在应用程序级别使用其他数据来完成同样的事情似乎是浪费。(更不用说,我的特定应用程序使用每字节收费的蜂窝链路。) 注意:根据我前面的问题-- --您不能依靠。Write引发异常来确定数据发送不正确。您可以使用TcpClient.SendTimeout来执行此操作。如果指定的超时在操作成功完成之前过期,则会导致写

是否有一种方法可以配置套接字在确定连接失败之前接收已发送数据的ACK的超时时间

我知道这也可以在应用程序级别上完成,但由于我发送的每个数据包都是经过确认的,我只想知道是否收到了我的数据,因此在应用程序级别使用其他数据来完成同样的事情似乎是浪费。(更不用说,我的特定应用程序使用每字节收费的蜂窝链路。)

注意:根据我前面的问题--
--您不能依靠
。Write
引发异常来确定数据发送不正确。

您可以使用
TcpClient.SendTimeout
来执行此操作。如果指定的超时在操作成功完成之前过期,则会导致写入操作抛出
SocketException

此外,有关如何设置具有更多可定制和可靠超时的套接字的更多信息,请参阅本页:

在一些IETF RFC()中提到了“用户超时”,它完成了要求的任务

其他一些操作系统将此作为套接字选项支持,但不幸的是,Windows不支持

如果没有此选项,在这种情况下,缩短中止时间的唯一方法是减少重传尝试次数,或减少初始RTT

在Windows上,前者可以通过netsh/registry进行控制(计算机范围..)

是否可以通过自己的超时放弃当前连接,并在需要时进行另一次连接

  • 应用程序必须确定何时放弃连接——可能是在TCP会话开始时根据不活动时间或有效数据速率确定的“生存时间”
  • 由于旧连接的重新传输,会有一点数据开销
  • 服务器应用可能需要更改以接受多个并发连接
  • 这个过程不应该被客户端不确定地重复,以防网络无法达到足够的超时速度
我不是一名C#专家,但我想我可以帮助回应。 您正试图从应用程序获取TCP层控制数据。这并不容易,就像任何应用层协议一样,您需要某种应用层响应,比如HTTP中的请求响应

知道您的所有写入数据实际上都是由另一端接收的问题在于TCP是面向流的。这意味着您可以通过套接字发送1KB的数据,KB存储在TCP snd缓冲区中,KB可以与3个TCP段一起发送,这3个TCP段可以被全部或单独确认(TCP ACK)。它是异步的。因此,在某个时刻,TCP可能只发送了1000 KB数据中的300字节,这只是一个例子

现在,另一个问题是,是每次发送数据块时打开连接并关闭连接(a),还是始终打开连接(B)

在(A)中,它更简单,因为如果连接无法打开,就是这样。超时可能需要一分钟以上,但您发送的IP和(20字节)TCP报头不超过几个(IP和TCP选项有时超过20字节)

在(B)中,当您想要发送数据时,您将意识到成功或失败。我会考虑以下三种情况:

1-套接字的另一端关闭或重置TCP连接。在这种情况下,您应该立即接收到错误响应,或者,在C语言中,一个指示管道破裂的信号,我想它在C语言中会成为一个例外

2-另一端无法连接,且未关闭/重置插座。这很难检测到,因为TCP将发送超时的消息,在几次重试/超时后,它将确定连接已断开。超时时间和重试次数可以配置,但在操作系统级别(适用于所有应用程序)。我认为你不能通过套接字配置它。 在这种情况下,应用程序在发送数据时无法实现

3-另一端成功接收数据并在TCP层确认

复杂的部分是尽可能快地区分(2)和(3)。我想你是在问这件事。 我不认为有任何可能完全做到这一点,除非你破解内核

无论如何,从应用层的服务器获得一个ACK可能意味着只有1或2个字节来告诉接收的数据量。除了IP和TCP基本头的20+20字节之外

如果有可能做到你所说的,我会尝试一下,但我从未测试过:

您可以使用发送缓冲区大小和选择功能。您可以使用setsockopt和OS_SNDBUF socket选项设置套接字的发送缓冲区大小。

如果您知道总是要发送2 KB的数据,请将发送缓冲区大小设置为2 KB。通常只有在连接后才能更改它。

然后调用套接字上的Select或Poll方法来检查它是否可写

只要确认了一条TCP消息,Select或Poll就应指示套接字可写,因为发送的数据已从发送缓冲区中删除

注意:此算法有局限性:

  • 操作系统可以定义最小缓冲区大小
  • 如果算法可行,Select和Poll将告诉您,当缓冲区空间可用时,套接字是可写的,但另一端实际上只接收并确认了数据的一部分
  • 如果发送可变大小的消息,则无法执行此操作
  • 如果无法应用上述算法,则可能需要使用应用层简单ACK支付额外的TCP消息的额外费用,该消息包含约42个字节

    很抱歉,无法提供最终解决方案。也许操作系统应该实现告诉您可用缓冲区字节的功能,这将解决您的问题