当前位置: 首页 > 知识库问答 >
问题:

缺少[FIN,ACK]和连接重置

孙文康
2023-03-14

我试图使用Apache的Java async HTTP客户端库开发对HTTP请求的代理链接支持。这主要是通过提供一些自定义的SchemeIOSessionStrategy类来完成的。我发现在配置多个代理时,[FIN,ACK]序列和丢失连接重置存在一些问题。

如果没有配置代理,正在开发的代码将独占地使用Apache库。如果配置了多个代理,则自定义SchemeIOSessionStrategy类提供连接到代理的安装程序。

若要通过代理进行连接,代码将打开到第一个代理服务器的连接,然后发出连接请求。如果代理服务器是链中的最后一个,它将连接到目标服务器,否则它将连接到链中的下一个代理服务器。所有设置完成后,将使用Apache库发送HTTP请求。

对于只有一个代理的配置,适用以下内容:客户机-->代理1-->HTTP服务器

有两个代理服务器:客户端-->代理1-->代理2-->HTTP服务器

目标是尽可能重用连接。当转到特定的HTTP服务器时,服务器会在空闲一段时间后关闭连接。如果使用相同的连接执行请求,代码将经历重新连接过程。

目前正在HTTP代理上进行测试,到代理的连接如下所示:

    HttpRequest request = null;

    String uri = _proxyHost.getTargetHost().getHostName() + ":" + _proxyHost.getTargetHost().getPort();
    ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 0);
    request = new BasicHttpRequest("CONNECT", uri, protocolVersion);

    if ((_proxyHost.getPrincipal() != null) && !_proxyHost.getPrincipal().isEmpty()) {
        StringBuilder builder = new StringBuilder(_proxyHost.getPrincipal());

        if ((_proxyHost.getCredentials() != null) && !_proxyHost.getCredentials().isEmpty()) {
            builder.append(":");
            builder.append(_proxyHost.getCredentials());
        }

        String encodedAuthString = DatatypeConverter.printBase64Binary(builder.toString().getBytes("UTF-8"));
        request.addHeader("Proxy-Authorization", "Basic " + encodedAuthString);
    }

    request.addHeader("Pragma", "No-Cache");
    request.addHeader("Proxy-Connection", "Keep-Alive");
    request.addHeader("Connection", "Keep-Alive");

要写入连接请求:

    StringBuilder builder = new StringBuilder();
    RequestLine requestLine = request.getRequestLine();

    builder.append(requestLine.getMethod());
    builder.append(" ");
    builder.append(requestLine.getUri());
    builder.append(" ");
    builder.append(requestLine.getProtocolVersion().toString());
    builder.append(CRLF);

    for (Header header : request.getAllHeaders()) {
        builder.append(header.toString());
        builder.append(CRLF);
    }

    builder.append(CRLF);

    ByteBuffer byteBuffer = ByteBuffer.wrap(builder.toString().getBytes());
    ioSession.channel().write(byteBuffer);

使用iosession.channel().read()准备好响应。ioSession是org.apache.http.nio.reactor.ioSession对象。

        HttpAsyncClientBuilder builder = HttpAsyncClients.custom().setRedirectStrategy(new LaxRedirectStrategy());
        ConnectingIOReactor ioReactor = IOReactorFactory.getInstance().createConnectingReactor();
        Registry<SchemeIOSessionStrategy> registry = generateRegistry(config);

        builder.setConnectionManager(new PoolingNHttpClientConnectionManager(ioReactor, registry));

        if (config.getProxy() != null) {
            proxyHost = new ProxyHost(config.getProxy());
            builder.setProxy(proxyHost);
        }

        CloseableHttpAsyncClient client = builder.build();
        client.start();

    RequestConfig.Builder configBuilder = RequestConfig.custom();
    configBuilder.setRedirectsEnabled(true);
    requestBuilder.setConfig(configBuilder.build());

    client.execute(requestBuilder.build(), context, handler);

客户端将挂起以下堆栈跟踪:

线程15996:(state=IN_NATIVE)-sun.nio.ch.fileDispatcherimpl.read0(java.io.fileDescriptor,long,int)@bci=0(编译帧;信息可能不精确)-sun.nio.ch.socketDispatcher.read(java.io.fileDescriptor,long,int)@bci=4(编译帧)-sun.nio.ch.socketDispatcher.read(java.io.fileDescriptor,long,int)@bci=4(编译帧)long,sun.nio.ch.nativeDispatcher)@bci=48(编译帧)-sun.nio.ch.socketchannelimpl.read(java.nio.bytebuffer)@bci=234(编译帧)-com...io.proxy.impl.passthroughchannel.read(java.nio.bytebuffer)-com...io.proxy.impl.passthroughchannel.read(java.nio.bytechannel)@bci=28,line=42(编译帧)PutBufferImpl.Fill(java.nio.channels.ReadableByteChannel)@bci=30,line=164(编译帧)-org.apache.http.impl.nio.codecs.abstractMessageParser.fillBuffer(java.nio.channels.readableByteChannel)@bci=5,line=136(编译帧)-org.apache.http.impl.nio.defaultNHttpClientConnection.consumeInput(org.apache.http.nio.nHttpClientEventHandler)@bci=38,line=241(编译帧)编译帧)-org.apache.http.impl.nio.client.internaliodispatch.oninputready(java.lang.object)@bci=5,line=37(编译帧)-org.apache.http.impl.nio.reactor.abstractiodispatch.inputtready(org.apache.http.nio.reactor.abstractiodispatch.inputtready(org.apache.http.nio.reactor.iosession)@bci=32,line=113(编译帧)ProcessEvent(java.nio.channels.selectionKey)@bci=45,line=338(编译帧)-org.apache.http.impl。processEvents(java.util.set)@bci=28,line=316(编译帧)-org.apache.http.impl.nio.reactor.abstractionoreactor.execute()@bci=80,line=277(编译帧)-org.apache.http.impl.nio.reactor.baseioreactor.execute(org.apache.http.nio.reactor.ioeventdispatch)@bci=13,line=105(解释帧)-org.apache.http.nio.reactor.abstrated run()@bci=11(已解释帧)

共有1个答案

潘衡
2023-03-14

我的第一个问题是为什么客户机不向Proxy1发送结束[FIN,ACK]?我找不到任何挂起的写入或其他可以找到的数据。

如果客户端从对等端接收到fin,但还没有发送,则客户端端口将处于close-wait状态,等待客户端本地应用程序关闭其套接字。客户机可能仍在尝试连接池,下次使用该连接时将发现关闭。

为什么链中不同数量的代理不同,这是一个谜,除非它以某种方式影响连接:头。也许Apache库会发送一个?

 类似资料:
  • 正如维基百科上所写,关闭TCP连接应该使用FIN数据包-

  • 有人能告诉我,为什么我不会得到一个异常,如果远程套接字正在关闭并发送FIN确认字符?Wireshark告诉我,FIN确认字符是由操作系统接收和发送的。 这是我的代码。我真的尝试了一切。 Instream是Socket.getInputStream(),Socket.getOutputStream()的外流。 连接将被我15秒的心跳关闭。

  • 在Mac OS X 10.8机器上,我有一台Tomcat 7.0.40服务器和一台客户端,都在本地运行。通过三方握手建立TCP连接,然后立即从服务器发送FIN、ACK和RST。客户端收到“来自服务器的文件结束”或“连接重置”。 TCP序列: 客户端SYN 服务器SYN,确认 客户端确认 服务器[TCP窗口更新]确认字符 服务器FIN,确认字符 客户端确认字符 服务器[TCP Dup确认字符]确认字

  • 我们刚刚从dbcp迁移到tomcat jdbc连池。我们在加载中尝试了系统,收到了以下异常: 请注意: 不忙的连接在哪里?忙的数字在这之后一直在下降,但我们仍然没有得到任何连接。 有什么想法吗? 配置: env:ubuntu和tomcat 6. db-mysql

  • 我有一个tcp客户端向tcp服务器发送HTTP POST请求。一旦建立连接,数据将从服务器传输到客户端。最后,服务器向客户端发送[FIN,ACK]。客户端发送一个ACK。37秒后,客户机发送[FIN,ACK],但客户机没有从服务器获得ACK,因此客户机继续在指数计时器上重新发送[FIN,ACK]。问题:是否允许客户端以37秒的延迟发送[FIN,ACK]?在这种情况下有没有标准的计时器值?在这种情况

  • 我正在尝试导出kafka连接指标。我的解决方案包括运行jmx导出器,并在endpoint处公开它们,然后可以使用Prometheus擦除。现在,我可以对我尝试过的所有指标都这样做,但对于一组指标,它不起作用。我对这组指标的导出配置如下 根据官方文档,这些指标的定义如下所示: 我想模式选择有问题,但我无法弄清楚是什么。请提供任何帮助或建议!!