/** * Simple constructor with the host and port to use to connect to. * <p>This constructor manages the lifecycle of the {@link TcpClient} and * underlying resources such as {@link ConnectionProvider}, * {@link LoopResources}, and {@link ChannelGroup}. * <p>For full control over the initialization and lifecycle of the * TcpClient, use {@link #ReactorNettyTcpClient(TcpClient, ReactorNettyCodec)}. * @param host the host to connect to * @param port the port to connect to * @param codec for encoding and decoding the input/output byte streams * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(String host, int port, ReactorNettyCodec<P> codec) { Assert.notNull(host, "host is required"); Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = TcpClient.create(this.poolResources) .host(host).port(port) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel())); }
@Override public ListenableFuture<Void> connect(final TcpConnectionHandler<P> handler) { Assert.notNull(handler, "TcpConnectionHandler is required"); if (this.stopping) { return handleShuttingDownConnectFailure(handler); } Mono<Void> connectMono = this.tcpClient .handle(new ReactorNettyHandler(handler)) .connect() .doOnError(handler::afterConnectFailure) .then(); return new MonoToListenableFutureAdapter<>(connectMono); }
/** * A variant of {@link #ReactorNettyTcpClient(String, int, ReactorNettyCodec)} * that still manages the lifecycle of the {@link TcpClient} and underlying * resources, but allows for direct configuration of other properties of the * client through a {@code Function<TcpClient, TcpClient>}. * @param clientConfigurer the configurer function * @param codec for encoding and decoding the input/output byte streams * @since 5.1.3 * @see org.springframework.messaging.simp.stomp.StompReactorNettyCodec */ public ReactorNettyTcpClient(Function<TcpClient, TcpClient> clientConfigurer, ReactorNettyCodec<P> codec) { Assert.notNull(codec, "ReactorNettyCodec is required"); this.channelGroup = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE); this.loopResources = LoopResources.create("tcp-client-loop"); this.poolResources = ConnectionProvider.elastic("tcp-client-pool"); this.codec = codec; this.tcpClient = clientConfigurer.apply(TcpClient .create(this.poolResources) .runOn(this.loopResources, false) .doOnConnected(conn -> this.channelGroup.add(conn.channel()))); }
@Test public void testTcpClient() throws InterruptedException { final CountDownLatch latch = new CountDownLatch(1); Connection client = TcpClient.create() .host("localhost") .port(echoServerPort) .handle((in, out) -> { in.receive() .log("conn") .subscribe(s -> latch.countDown()); return out.sendString(Flux.just("Hello World!")) .neverComplete(); }) .wiretap(true) .connectNow(); latch.await(30, TimeUnit.SECONDS); client.disposeNow(); assertThat("latch was counted down", latch.getCount(), is(0L)); }
private WebsocketClientTransport createRSocketTransport(ClientSettings settings) { String path = "/"; HttpClient httpClient = HttpClient.newConnection() .followRedirect(settings.followRedirect()) .tcpConfiguration( tcpClient -> { if (settings.sslProvider() != null) { tcpClient = tcpClient.secure(settings.sslProvider()); } return tcpClient.runOn(loopResources).host(settings.host()).port(settings.port()); }); return WebsocketClientTransport.create(httpClient, path); }
/** * Creates a new instance * * @param bindAddress the address to connect to * @param port the port to connect to * @return a new instance * @throws NullPointerException if {@code bindAddress} is {@code null} */ public static TcpClientTransport create(String bindAddress, int port) { Objects.requireNonNull(bindAddress, "bindAddress must not be null"); TcpClient tcpClient = TcpClient.create().host(bindAddress).port(port); return create(tcpClient); }
/** * Creates TcpClient for target address. * * @param address connect address * @return tcp client */ private TcpClient newTcpClient(Address address) { return TcpClient.create(ConnectionProvider.newConnection()) .runOn(loopResources) .host(address.host()) .port(address.port()) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.SO_REUSEADDR, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, config.getConnectTimeout()) .bootstrap(b -> BootstrapHandlers.updateConfiguration(b, "outbound", channelInitializer)); }
@Test public void testTcpClient1ThreadAcquire() { LoopResources resources = LoopResources.create("test", 1, true); Connection client = TcpClient.create() .host("localhost") .port(echoServerPort) .runOn(resources) .wiretap(true) .connectNow(); client.disposeNow(); resources.dispose(); assertThat("client was configured", client instanceof ChannelOperations); }
private Mono<RSocket> connect(Address address, Map<Address, Mono<RSocket>> monoMap) { TcpClient tcpClient = TcpClient.newConnection() // create non-pooled .runOn(loopResources) .host(address.host()) .port(address.port());
TcpClient.create() .port(server.address().getPort()) .doOnConnected(c -> c.addHandlerLast("codec", new LineBasedFrameDecoder(256))) .handle((in, out) -> out.options(sendOptions -> sendOptions.flushOnEach(false)) .sendString(Flux.just("1\n", "2\n", "3\n", "4\n")) .connectNow();
private static WebClientProvider getWebClientProvider(ClientConfiguration clientConfiguration) { Duration connectTimeout = clientConfiguration.getConnectTimeout(); Duration soTimeout = clientConfiguration.getSocketTimeout(); TcpClient tcpClient = TcpClient.create(); if (!connectTimeout.isNegative()) { tcpClient = tcpClient.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, Math.toIntExact(connectTimeout.toMillis())); } if (!soTimeout.isNegative()) { tcpClient = tcpClient.doOnConnected(connection -> connection // .addHandlerLast(new ReadTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS)) .addHandlerLast(new WriteTimeoutHandler(soTimeout.toMillis(), TimeUnit.MILLISECONDS))); } String scheme = "http"; HttpClient httpClient = HttpClient.from(tcpClient); if (clientConfiguration.useSsl()) { httpClient = httpClient.secure(sslConfig -> { Optional<SSLContext> sslContext = clientConfiguration.getSslContext(); sslContext.ifPresent(it -> sslConfig.sslContext(new JdkSslContext(it, true, ClientAuth.NONE))); }); scheme = "https"; } ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient); WebClientProvider provider = WebClientProvider.create(scheme, connector); return provider.withDefaultHeaders(clientConfiguration.getDefaultHeaders()); }
/** * Creates a new instance * * @param address the address to connect to * @return a new instance * @throws NullPointerException if {@code address} is {@code null} */ public static TcpClientTransport create(InetSocketAddress address) { Objects.requireNonNull(address, "address must not be null"); TcpClient tcpClient = TcpClient.create().addressSupplier(() -> address); return create(tcpClient); }
clientTransportFactory = address -> { TcpClient client = TcpClient.create().addressSupplier(() -> address); return TcpClientTransport.create(client); }; address -> { TcpClient client = TcpClient.create().addressSupplier(() -> address).secure(sslContext); return TcpClientTransport.create(client); };
@Test public void closingPromiseIsFulfilled() { TcpClient client = TcpClient.newConnection() .host("localhost") .port(abortServerPort); client.handle((in, out) -> Mono.empty()) .wiretap(true) .connectNow() .disposeNow(); }
private static HttpClient initHttpClient(ReactorResourceFactory resourceFactory) { ConnectionProvider provider = resourceFactory.getConnectionProvider(); LoopResources resources = resourceFactory.getLoopResources(); Assert.notNull(provider, "No ConnectionProvider: is ReactorResourceFactory not initialized yet?"); Assert.notNull(resources, "No LoopResources: is ReactorResourceFactory not initialized yet?"); return HttpClient.create(provider).tcpConfiguration(tcpClient -> tcpClient.runOn(resources)); }
@Override @SuppressWarnings("unchecked") public Mono<WebsocketClientOperations> connect() { return (Mono<WebsocketClientOperations>)cachedConfiguration.connect(); }