a vu votre conversation dans IRC#netty.
Un certain nombre de choses ici. Votre proxy doit avoir un côté serveur auquel le serveur 1 se connecte. Ensuite, le serveur 2 et le serveur 3 doivent soit être en dehors d'une connexion à partir du proxy, soit utiliser UDP (en fonction de) pour recevoir des données du proxy.
Netty a un exemple de serveur proxy. Cela fonctionnerait dans votre cas et c'est vraiment facile pour la troisième partie. Autrement dit, vous utiliserez l'exemple existant et ouvrirez une nouvelle connexion qui sera vers le serveur 3. Maintenant, vous pouvez prendre les deux canaux du proxy (connexions client vers les serveurs 2 et 3). Mettez-les dans un groupe de canaux et écrivez-en un temps à deux serveurs !. Mon exemple de code éditer va permettre les communications du serveur 1 vers le serveur 2 via le proxy mutuellement et permettre une conversation mutuelle tandis que le serveur 3 ne peut recevoir que des données mais si le serveur 3 répond au proxy, le proxy ne fait rien . Vous voudrez peut-être ajouter un gestionnaire pour libérer des tampons ou gérer des données écrites qui ne devraient pas provenir du serveur 3. De là, vous devriez commencer mais vérifiez les documents netty, api, exemples et ppts ils sont super utiles!
Je vais joindre un code modifié pour vous montrer et voici un lien vers les exemples.
Netty Proxy Server Examples
Donc, pour l'exemple, vous modifier le HexDumpProxyFrontendHandler.class et il suffit d'ajouter un deuxième Bootstrap pour le nouveau client pour le serveur 3.
Code actuel
41 @Override
42 public void channelActive(ChannelHandlerContext ctx) {
43 final Channel inboundChannel = ctx.channel();
44
45 // Start the connection attempt.
46 Bootstrap b = new Bootstrap();
47 b.group(inboundChannel.eventLoop())
48 .channel(ctx.channel().getClass())
49 .handler(new HexDumpProxyBackendHandler(inboundChannel))
50 .option(ChannelOption.AUTO_READ, false);
51 ChannelFuture f = b.connect(remoteHost, remotePort);
52 outboundChannel = f.channel();
53 f.addListener(new ChannelFutureListener() {
54 @Override
55 public void operationComplete(ChannelFuture future) {
56 if (future.isSuccess()) {
57 // connection complete start to read first data
58 inboundChannel.read();
59 } else {
60 // Close the connection if the connection attempt has failed.
61 inboundChannel.close();
62 }
63 }
64 });
65 }
Modifié code
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
/*
* Copyright 2012 The Netty Project
*
* The Netty Project licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package io.netty.example.proxy;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter {
private final String remoteHost;
private final int remotePort;
// As we use inboundChannel.eventLoop() when buildling the Bootstrap this does not need to be volatile as
// the server2OutboundChannel will use the same EventLoop (and therefore Thread) as the inboundChannel.
private Channel server2OutboundChannel;
private Channel server3OutboundChannel;
// TODO You should change this to your own executor
private ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
public HexDumpProxyFrontendHandler(String remoteHost, int remotePort) {
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
final Channel inboundChannel = ctx.channel();
// Start the connection attempt to SERVER 3
Bootstrap server3Bootstrap = new Bootstrap();
server3Bootstrap.group(inboundChannel.eventLoop())
.channel(ctx.channel().getClass())
// You are only writing traffic to server 3 so you do not need to have a handler for the inbound traffic
.handler(new DiscardServerHandler()) // EDIT
.option(ChannelOption.AUTO_READ, false);
ChannelFuture server3Future = server3Bootstrap.connect(remoteHost, remotePort);
server3OutboundChannel = server3Future.channel();
// Start the connection attempt to SERVER 2
Bootstrap server2Bootstrap = new Bootstrap();
server2Bootstrap.group(inboundChannel.eventLoop())
.channel(ctx.channel().getClass())
.handler(new HexDumpProxyBackendHandler(inboundChannel))
.option(ChannelOption.AUTO_READ, false);
ChannelFuture server2Future = server2Bootstrap.connect(remoteHost, remotePort);
server2OutboundChannel = server2Future.channel();
server2Future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// connection complete start to read first data
inboundChannel.read();
} else {
// Close the connection if the connection attempt has failed.
inboundChannel.close();
}
}
});
// Here we are going to add channels to channel group to save bytebuf work
channels.add(server2OutboundChannel);
channels.add(server3OutboundChannel);
}
// You can keep this the same below or use the commented out section
@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) {
// You need to reference count the message +1
msg.retain();
if (server2OutboundChannel.isActive()) {
server2OutboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// was able to flush out data, start to read the next chunk
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
if (server3OutboundChannel.isActive()) {
server3OutboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// was able to flush out data, start to read the next chunk
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
// Optional to the above code instead channel writing automatically cares for reference counting for you
// channels.writeAndFlush(msg).addListeners(new ChannelFutureListener() {
//
// @Override
// public void operationComplete(ChannelFuture future) throws Exception {
// if (future.isSuccess()) {
// // was able to flush out data, start to read the next chunk
// ctx.channel().read();
// } else {
// future.channel().close();
// }
// }
// });
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
if (server2OutboundChannel != null) {
closeOnFlush(server2OutboundChannel);
}
if (server3OutboundChannel != null) {
closeOnFlush(server3OutboundChannel);
}
// Optionally can do this
// channels.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
closeOnFlush(ctx.channel());
}
/**
* Closes the specified channel after all queued write requests are flushed.
*/
static void closeOnFlush(Channel ch) {
if (ch.isActive()) {
ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
}
}
Jeter Handler
Cela pourrait être ajouté au serveur 3 en tant que gestionnaire pour rejeter tout ce qui a été écrit dans le proxy par le serveur 3. Par défaut, SimpleInboundHandlers supprimera les messages après leur traitement en décrémentant le nombre de références.
Discard Handler Code
merci beaucoup pour votre réponse, je vais aller sur tout cela et de revenir à vous ... – tsar2512
fait cela automatiquement que si assurer le serveur 3 est bloqué, ou a un ralentissement, il ne sera pas l'impact ou ralentir la communication entre le serveur 1 -> le serveur 2? – tsar2512
La seule charge supplémentaire est que les données quittent votre socket vers le serveur 3 en plus du serveur 2. Le traitement interne utilisant le groupe de canaux ne devrait pas beaucoup affecter les performances. Le serveur 3 peut encore écrire techniquement sur le proxy, mais les données ne seront pas traitées. Vous pouvez insérer un gestionnaire de rejet. Modifié la réponse pour inclure un gestionnaire de suppression pour la connexion sur le proxy au serveur 3, toutes les données du serveur 3 sont maintenant supprimées si elles sont écrites sur le proxy. – Underbalanced