有没有一种方法可以模拟Socket和Connection超时?

时间:2020-08-08 05:31:45

标签: java http httpurlconnection socket-timeout-exception

我有一段代码使用HTTP连接与第三方集成,从而以不同的方式处理套接字超时和连接超时。

我一直在尝试模拟和测试可能来自第三方的所有情况。通过连接到服务器防火墙阻止的端口能够测试连接超时端口81。

但是我无法模拟套接字超时。如果我的理解是正确的,那么套接字超时与连续的数据包流相关联,并且连接之间处于断开状态。有什么方法可以模拟吗?

2 个答案:

答案 0 :(得分:0)

所以我们在这里讨论的超时是各种超时,一种是连接到服务器(连接超时),另一种超时会发生在一段时间内没有通过套接字发送或接收数据时(空闲超时)。< /p>

节点套接字有一个套接字超时,可用于综合连接和空闲超时。这可以通过将套接字超时设置为连接超时,然后在连接时将其设置为空闲超时来完成。

示例:

        const request = http.request(url, {
            timeout: connectTimeout,
        });
        request.setTimeout(idleTimeout);

这是可行的,因为在创建套接字时会立即设置选项中的超时,setTimeout 函数在连接时在套接字上运行!

无论如何,问题是关于如何测试连接超时。好的,让我们首先暂停空闲超时。我们可以通过在一段时间内不发送任何数据来简单地测试,这会导致超时。检查!

连接超时有点难测试,首先想到的是我们需要一个不会出错但也不会连接的地方来连接。这会导致超时。但是我们到底如何在节点中模拟它?

如果我们跳出框框思考一下,那么我们可能会发现这个超时时间大约是连接所需的时间。为什么连接需要那么长时间并不重要。我们只需要延迟连接所需的时间。这不一定是服务器的事情,我们也可以在客户端上做。毕竟这是连接的部分,如果我们可以延迟到那里,我们可以测试超时。

那么我们怎么能延迟客户端的连接呢?好吧,我们可以使用 DNS 查找。在建立连接之前,会进行 DNS 查找。如果我们只是将其延迟 5 秒左右,我们可以很容易地测试连接超时。

代码如下:

import * as dns from "dns";
import * as http from "http";

const url = new URL("http://localhost:8080");

const request = http.request(url, {
    timeout: 3 * 1000, // connect timeout
    lookup(hostname, options, callback) {
        setTimeout(
            () => dns.lookup(hostname, options, callback),
            5 * 1000,
        );
    },
});
request.setTimeout(10 * 1000); // idle timeout

request.addListener("timeout", () => {
    const message = !request.socket || request.socket.connecting ?
        `connect timeout while connecting to ${url.href}` :
        `idle timeout while connected to ${url.href}`;

    request.destroy(new Error(message));
});

在我的项目中,我通常使用我注入的代理。然后代理进行延迟查找。像这样:

import * as dns from "dns";
import * as http from "http";

const url = new URL("http://localhost:8080");

const agent = new http.Agent({
    lookup(hostname, options, callback) {
        setTimeout(
            () => dns.lookup(hostname, options, callback),
            5 * 1000,
        );
    },
});

const request = http.request(url, {
    timeout: 3 * 1000, // connect timeout
    agent,
});
request.setTimeout(10 * 1000); // idle timeout

request.addListener("timeout", () => {
    const message = !request.socket || request.socket.connecting ?
        `connect timeout while connecting to ${url.href}` :
        `idle timeout while connected to ${url.href}`;

    request.destroy(new Error(message));
});

快乐编码!

答案 1 :(得分:-1)

“连接超时”确定建立TCP连接可能需要多长时间,而这一切都发生在通过该行发送任何HTTP相关数据之前。通过连接到阻塞的端口,由于未建立连接,因此您仅测试了部分连接超时。通常,将非常快速地创建(建立)本地网络上的TCP连接。但是,当连接到世界另一端的服务器时,建立TCP连接可能需要几秒钟。

“套接字超时”是一个有点令人误解的名称-它仅确定您(客户端)将等待服务器的答案(数据)多长时间。换句话说,Socket.read()函数在等待数据时将阻塞多长时间。

正确测试这些功能涉及创建服务器套接字或(HTTP)Web服务器,您可以对其进行修改以使其变慢。描述如何创建和使用服务器套接字进行连接超时测试(如果可能的话)在这里无法回答,但是套接字超时测试是一个常见的问题-例如,请参见here(我只是用谷歌搜索“模拟网络”服务器来测试超时”),这会导致产生类似MockWebServer之类的工具。 “ MockWebServer”可能还可以选择测试连接超时(我没有使用“ MockWebServer”),但是如果没有,则可能有另一个工具。

最后一点:最好在超时设置方面测试第三方HTTP库的使用,即使这需要一些努力。可能发生的最坏情况是库中不使用代码中的套接字超时设置,而是使用默认的套接字超时“永远等待”。这可能会导致您的应用程序无缘无故地做任何事情(“挂起”)。