2016-07-16 2 views
0

Я попытался отправить одно сообщение на многие серверы через netty и просто отбросить ответ сервера. Я подготовил маленький пример с реализацией, пожалуйста, смотрите на ниже:Netty: проблема с отправкой сообщения на многие серверы

import io.netty.bootstrap.Bootstrap; 
import io.netty.buffer.ByteBuf; 
import io.netty.buffer.Unpooled; 
import io.netty.channel.ChannelFuture; 
import io.netty.channel.ChannelInitializer; 
import io.netty.channel.ChannelOption; 
import io.netty.channel.ChannelPipeline; 
import io.netty.channel.EventLoopGroup; 
import io.netty.channel.nio.NioEventLoopGroup; 
import io.netty.channel.socket.SocketChannel; 
import io.netty.channel.socket.nio.NioSocketChannel; 
import java.util.LinkedList; 
import java.util.List; 

public class MainTest { 

    private final List<ConnectionInfo> HOSTS = new LinkedList<>(); 
    private final ByteBuf buf; 

    public MainTest() { 
     HOSTS.add(new ConnectionInfo("127.0.0.1", 10000)); 
     HOSTS.add(new ConnectionInfo("127.0.0.1", 20000)); 
     HOSTS.add(new ConnectionInfo("127.0.0.1", 30000)); 
     HOSTS.add(new ConnectionInfo("127.0.0.1", 40000)); 
     HOSTS.add(new ConnectionInfo("127.0.0.1", 50000)); 

     buf = Unpooled.buffer(100); 
     for (int i = 0; i < buf.capacity(); i ++) { 
      buf.writeByte((byte) i); 
     } 
    } 

    public static void main(String[] args) throws InterruptedException { 
     new MainTest().start(); 
    } 

    public void start() throws InterruptedException { 
     for (ConnectionInfo connectionInfo : HOSTS) { 
      // Configure the client. 
      EventLoopGroup group = new NioEventLoopGroup(); 
      try { 
       Bootstrap b = new Bootstrap(); 
       b.group(group) 
         .channel(NioSocketChannel.class) 
         .option(ChannelOption.TCP_NODELAY, true) 
         .handler(new ChannelInitializer<SocketChannel>() { 
          @Override 
          public void initChannel(SocketChannel ch) throws Exception { 
           ChannelPipeline p = ch.pipeline(); 
           //p.addLast(new LoggingHandler(LogLevel.INFO)); 
           p.addLast(new EchoClientHandler(buf.copy())); 
          } 
         }); 
       // Start the client. 
       ChannelFuture f = b.connect(connectionInfo.getHost(), connectionInfo.getPort()).sync(); 
       // Wait until the connection is closed. 
       f.channel().closeFuture().sync(); 
      } finally { 
       // Shut down the event loop to terminate all threads. 
       group.shutdownGracefully(); 
      } 
     } 
    } 

    private class ConnectionInfo { 
     private final String host; 
     private final int port; 

     public ConnectionInfo(String host, int port) { 
      this.host = host; 
      this.port = port; 
     } 

     public String getHost() { 
      return host; 
     } 

     public int getPort() { 
      return port; 
     } 
    } 
} 

и EchoClientHandler класс:

import io.netty.buffer.ByteBuf; 
import io.netty.channel.ChannelHandlerContext; 
import io.netty.channel.ChannelInboundHandlerAdapter; 

public class EchoClientHandler extends ChannelInboundHandlerAdapter { 

    private final ByteBuf message; 

    public EchoClientHandler(ByteBuf buf) { 
     message = buf; 
    } 

    @Override 
    public void channelActive(ChannelHandlerContext ctx) { 
     ctx.writeAndFlush(message); 
     ctx.close(); 
    } 

    @Override 
    public void channelReadComplete(ChannelHandlerContext ctx) { 
     ctx.flush(); 
    } 

    @Override 
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
     cause.printStackTrace(); 
     ctx.close(); 
    } 
} 

, но если какой-то сервер из списка недоступен цикл будет прерван. Я хотел бы это исправить. У вас есть идеи для этого?

+0

Чтобы отправить одно сообщение на множество устройств одновременно, вы должны использовать многоадресную рассылку. Получатели должны подписаться на группу многоадресной рассылки, и отправитель просто отправляет сообщение группе многоадресной рассылки. Это именно та проблема, для которой многоадресная рассылка была разработана как решение. –

+0

@ RonMaupin конечно, но не для этого случая. это просто тестовый пример для netty, ничего серьезного. Но если у вас есть примеры использования многоадресной рассылки в java, поделитесь ею со мной. –

ответ

1

Я нашел 2 решения:

  1. код обруча в петле в теме класс.
  2. отключить синхронизацию при подключении к серверу

Рассмотрим эти 2 решения в коде.

1. Wrap:

for (ConnectionInfo connectionInfo : HOSTS) { 
    new Thread() { 
    public void run() { 
     // Configure the client. 
     EventLoopGroup group = new NioEventLoopGroup(); 
     try { 
     Bootstrap b = new Bootstrap(); 
     // ....... etc 
     } finally { 
     // Shut down the event loop to terminate all threads. 
     group.shutdownGracefully(); 
     } 
    } 
    }.start(); 
} 

2. Отключение синхронизации (и добавить некоторые каротаж):

// Start the client. 
ChannelFuture f = b.connect(connectionInfo.getHost(), connectionInfo.getPort()); 
f.addListener(new ChannelFutureListener() { 
    @Override 
    public void operationComplete(ChannelFuture future) { 
    if (future.isSuccess()) { 
     // connection complete start to read first data 
     LOG.log(Level.INFO, "Connected to {0}:{1} successfully.", 
      new Object[]{connectionInfo.getHost(), connectionInfo.getPort().toString()}); 
    } else { 
     // Close the connection if the connection attempt has failed. 
     LOG.log(Level.WARNING, "Connection problem to {0}:{1}.", 
      new Object[]{connectionInfo.getHost(), connectionInfo.getPort().toString()}); 
    } 
    } 
}); 
// Wait until the connection is closed. 
f.channel().closeFuture().sync(); 

Второе решение выглядит более легким, и я предпочитаю его.

Смежные вопросы