简体   繁体   English

防止TCP套接字连接重试

[英]Prevent TCP socket connection retries

How can I prevent TCP from making multiple socket connection attempts? 如何防止TCP进行多个套接字连接尝试?

Background 背景

I'm trying to get a rough estimate of the round-trip-time to a client. 我试图粗略估计一下客户的往返时间。 The high-level protocol I have to work with gives no way to determine the RTT, nor does it have any sort of no-op reqeust/response flow. 我必须使用的高级协议无法确定RTT,也没有任何类型的无操作请求/响应流程。 So, I'm attempting to get information directly from the lower layers. 所以,我试图直接从较低层获取信息。 In particular, I know that the client will actively reject TCP connection attempts on a particular port. 特别是,我知道客户端将主动拒绝特定端口上的TCP连接尝试。

Me -> Client: SYN
Client -> Me: ACK, RST

Code

  long lStartTime = System.nanoTime() / 1000000;
  long lEndTime;

  // Attempt to connect to the remote party.  We don't mind whether this
  // succeeds or fails.
  try
  {
    // Connect to the remote system.
    lSocket.connect(mTarget, MAX_PING_TIME_MS);

    // Record the end time.
    lEndTime = System.nanoTime() / 1000000;

    // Close the socket.
    lSocket.close();
  }
  catch (SocketTimeoutException|IOException lEx)
  {
    lEndTime = System.nanoTime() / 1000000;
  }

  // Calculate the interval.
  lInterval = lEndTime - lStartTime;
  System.out.println("Interval = " + lInterval);

Problem 问题

Using Wireshark, I see that the call to lSocket.connect makes three (failed) attempts to connect the socket before giving up - with an apparently arbitrary inter-attempt interval (often ~300ms). 使用Wireshark,我看到对lSocket.connect的调用使得三次(失败)尝试在放弃之前连接套接字 - 显然是任意的尝试间间隔(通常为~300ms)。

Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST

Question

Is there any way to make TCP give up after a single SYN/RST pair? 有没有办法让TCP在单个SYN / RST对之后放弃?

I've looked through some of the Java code. 我查看了一些Java代码。 I wondered if I was on to a winner when the comment on AbstractPlainSocketImpl said... AbstractPlainSocketImpl上的评论说...时,我想知道我是不是赢了。

/**
 * The workhorse of the connection operation.  Tries several times to
 * establish a connection to the given <host, port>.  If unsuccessful,
 * throws an IOException indicating what went wrong.
 */

...but sadly there's no evidence of looping/retries in that function or any of the other (non-native) functions that I've looked at. ...但遗憾的是,没有证据表明该函数或我所看到的任何其他(非本机)函数存在循环/重试。

Where does this retry behaviour actually come from? 这种重试行为实际上来自哪里? And how can it be controlled? 它怎么能被控制?

Alternatives 备择方案

I may also be open to alternatives, but not... 我也可以接受替代方案,但不是......

  • Using ICMP echo requests (pings). 使用ICMP回应请求(ping)。 I know that many clients won't respond to them. 我知道许多客户不会回复他们。
  • Using raw sockets. 使用原始套接字。 One of the platforms is Windows, which these days severely limits the ability to use raw sockets. 其中一个平台是Windows,这些天严重限制了使用原始套接字的能力。 (I also think the Linux network stack jumps in unhelpfully if it's caught in the cross-fire of an application trying to use a raw socket to do TCP.) (我还认为,如果Linux网络堆栈遇到了试图使用原始套接字来执行TCP的应用程序的交叉攻击,那么Linux网络堆栈就无济于事。)
  • Using the JNI, except as a last resort. 使用JNI,除非作为最后的手段。 My code needs to work on at least 2 very different operating systems. 我的代码需要在至少2个非常不同的操作系统上工作。

TCP connect retries are a function of the OS's socket implementation. TCP连接重试是OS的套接字实现的一个功能。 Configuring this depends on the platform. 配置这取决于平台。 See https://security.stackexchange.com/questions/34607/why-is-the-server-returning-3-syn-ack-packets-during-a-syn-scan for a description of what this is and why it is happening. 请参阅https://security.stackexchange.com/questions/34607/why-is-the-server-returning-3-syn-ack-packets-during-a-syn-scan ,了解这是什么以及为什么正在发生。

On Windows, you should be able to modify the retry count in the registry: 在Windows上,您应该能够修改注册表中的重试次数:

Settings related to the RTT are detailed in that documentation as well. 与RTT相关的设置也在该文档中详细说明。

On Linux, the accepted answer in the linked Security post talks about how to configure this parameter: 在Linux上,链接的安全帖子中接受的答案讨论了如何配置此参数:

On a Linux system, see the special files in /proc/sys/net/ipv4/ called tcp_syn_retries and tcp_synack_retries : they contain the number of times the kernel would emit SYN (respectively SYN+ACK) on a given connection ... this is as simple as echo 3 > tcp_synack_retries ... 在Linux系统上,请参阅/proc/sys/net/ipv4/的特殊文件tcp_syn_retriestcp_synack_retries :它们包含内核在给定连接上发出SYN(分别为SYN + ACK)的次数...这是就像echo 3 > tcp_synack_retries一样简单......

Note that this is a system-wide setting. 请注意,这是一个系统范围的设置。

You can read the current values by reading the registry settings (on Windows) or reading the contents of the special files (on Linux). 您可以通过读取注册表设置(在Windows上)或读取特殊文件的内容(在Linux上)来读取当前值。

Also, MSDN has this to say about the TCP connect RTT on Windows: 此外,MSDN有关于Windows上TCP连接RTT的说法:

TCP/IP adjusts the frequency of retransmissions over time. TCP / IP随时间调整重传频率。 The delay between the original transmission and the first retransmission for each interface is determined by the value of the TcpInitialRTT entry. 每个接口的原始传输和第一次重传之间的延迟由TcpInitialRTT条目的值确定。 By default, it is three seconds. 默认情况下,它是三秒钟。 This delay doubles after each attempt. 每次尝试后,此延迟加倍。 After the final attempt, TCP/IP waits for an interval equal to double the last delay, and then it abandons the connection request. 在最后一次尝试之后,TCP / IP等待的间隔等于上一次延迟的两倍,然后它放弃连接请求。

By the way, re: raw sockets - Yes, you would have an extremely difficult time. 顺便说一句,重新:原始套接字 - 是的,你将有一个非常困难的时间。 Also, as of Windows XP SP2, Windows won't actually let you specify TCP protocol numbers for raw sockets under any circumstances (see Limitations). 此外,从Windows XP SP2开始,Windows 实际上不允许您在任何情况下为原始套接字指定TCP协议号 (请参阅限制)。

Also, as an aside: Make sure that the TCP connection is not being blocked by a separate firewall in front of the client, otherwise you only end up measuring round trip time to the firewall. 另外,请注意:确保TCP连接没有被客户端前面的单独防火墙阻止,否则您最终只能测量到防火墙的往返时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM