如何防止TCP进行多个套接字连接尝试?
背景
我正在尝试粗略估计到客户端的往返时间(RTT)。我需要使用的高级协议没有办法确定RTT,也没有任何形式的no-op请求/响应流。因此,我试图直接从较低的层面获取信息。特别是,我知道客户端将主动拒绝特定端口上的TCP连接尝试。
Me -> Client: SYN
Client -> Me: ACK, RST
代码
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);
问题
使用Wireshark,我发现对lSocket.connect
的调用在放弃之前尝试连接套接字三次(都失败了),每次间隔似乎是任意的(通常约为300毫秒)。
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
Me -> Client: SYN
Client -> Me: ACK, RST
问题
是否有一种方法让TCP在仅经历一个SYN/RST对后放弃连接尝试?
我查看了一些Java代码。当我看到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.
*/
但遗憾的是,在我查看的那个函数或任何其他(非本机)函数中,都没有循环/重试的证据。
这种重试行为实际上来自哪里?如何控制它?
替代方案
我可能也会接受替代方案,但不包括以下内容:
- 使用ICMP回显请求(ping)。 我知道许多客户端不会响应它们。
- 使用原始套接字。 其中一个平台是Windows,现在严重限制了使用原始套接字的能力。(我还认为Linux网络堆栈会不理智地跳入其中,如果应用程序尝试使用原始套接字来执行TCP。)
- 除了作为最后的手段之外,不使用JNI。 我的代码需要在至少两个非常不同的操作系统上运行。
SocketException
中(不记得是哪个了) - fge