Java 每个远程主机具有不同管道的UDP不工作
我在与UDP合作时遇到了麻烦。最大的问题是,一旦我连接到服务器并完成服务器和客户端之间的交互,服务器就变得无用了。我无法从同一个客户端或任何其他(不同的主机)与它建立任何其他连接。我觉得他们的东西真的很简单,我错过了。我已将服务器配置为使用以下代码为每个连接到它的新主机创建一个新管道(我想是?):Java 每个远程主机具有不同管道的UDP不工作,java,network-programming,netty,nio,Java,Network Programming,Netty,Nio,我在与UDP合作时遇到了麻烦。最大的问题是,一旦我连接到服务器并完成服务器和客户端之间的交互,服务器就变得无用了。我无法从同一个客户端或任何其他(不同的主机)与它建立任何其他连接。我觉得他们的东西真的很简单,我错过了。我已将服务器配置为使用以下代码为每个连接到它的新主机创建一个新管道(我想是?): public class DistinctChannelPipelineFactory implements ChannelPipelineFactory { private final Cha
public class DistinctChannelPipelineFactory implements ChannelPipelineFactory {
private final ChannelPipelineFactory pipelineFactory;
public DistinctChannelPipelineFactory(ChannelPipelineFactory pipelineFactory) {
this.pipelineFactory = pipelineFactory;
}
@Override public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new DistinctChannelPipelineHandler(pipelineFactory));
}
}
在DistinctChannelPipelineHandler中,我尝试为每个远程主机创建一个不同的管道,并在10秒后对它们进行计时
private final LoadingCache<SocketAddress, ChannelPipeline> pipelines;
public DistinctChannelPipelineHandler(ChannelPipelineFactory factory) {
this.pipelines = CacheBuilder.newBuilder()
.concurrencyLevel(1)
.expireAfterAccess(10, SECONDS)
.removalListener(new PipelineRemovalListener())
.build(new PipelineCacheLoader(factory));
}
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof MessageEvent) {
final ChannelPipeline pipeline = pipelines.get(((MessageEvent) e).getRemoteAddress());
if (!pipeline.isAttached()) {
pipeline.attach(ctx.getChannel(), ctx.getPipeline().getSink());
pipeline.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(), OPEN, TRUE));
}
pipeline.sendUpstream(e);
}
if (e instanceof ChannelStateEvent) {
for (final ChannelPipeline pipeline : pipelines.asMap().values()) {
final ChannelStateEvent cse = (ChannelStateEvent) e;
pipeline.sendUpstream(new UpstreamChannelStateEvent(ctx.getChannel(), cse.getState(), cse.getValue()));
}
}
}
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof MessageEvent) {
final ChannelPipeline pipeline = pipelines.get(((MessageEvent) e).getRemoteAddress());
if (!pipeline.isAttached()) {
pipeline.attach(ctx.getChannel(), ctx.getPipeline().getSink());
}
pipeline.sendDownstream(e);
} else {
ctx.sendDownstream(e);
}
}
private static final class PipelineCacheLoader extends CacheLoader<SocketAddress, ChannelPipeline> {
private final ChannelPipelineFactory factory;
public PipelineCacheLoader(ChannelPipelineFactory factory) {
this.factory = factory;
}
@Override
public ChannelPipeline load(SocketAddress key) throws Exception {
return factory.getPipeline();
}
}
private static final class PipelineRemovalListener implements RemovalListener<SocketAddress, ChannelPipeline> {
private static final Logger logger = LoggerFactory.getLogger(PipelineRemovalListener.class);
@Override
public void onRemoval(RemovalNotification<SocketAddress, ChannelPipeline> n) {
logger.info("UDP connection timed out, removing connection for {}", n.getKey());
n.getValue().sendUpstream(new UpstreamChannelStateEvent(n.getValue().getChannel(), OPEN, FALSE));
}
}
我忽略了实际添加所有处理程序的位置,因为我认为这不是问题所在。我是不是错过了一些基本的东西?我只希望每个超时的唯一远程地址都有一个管道。启动服务器并让它只在客户端/服务器交互中工作,这是非常令人沮丧的!我已经通过调试验证了,一旦我用额外的请求点击它,它就不会创建新的管道。因此,原始管道似乎处于非常陈旧的状态,这就是它不接受任何其他请求的原因。思想?建议?犯了一个根本性的错误。使用ConnectionlessBootstrap,所有内容都在同一个通道上运行,每次调用服务器后,我们都会关闭该通道……从而禁用UDP。这就是我们的TCP代码所做的,花了一段时间才意识到它的工作方式有所不同。希望其他人能为此节省一些时间和麻烦
@Provides
public ConnectionlessBootstrap getConnectionlessBootstrap(DatagramChannelFactory channelFactory,
@LocalAddress SocketAddress localAddress,
final UdpPipelineFactory pipelineFactory) {
final ConnectionlessBootstrap bootstrap = new ConnectionlessBootstrap(channelFactory);
bootstrap.setOption("localAddress", localAddress);
bootstrap.setPipelineFactory(new DistinctChannelPipelineFactory(pipelineFactory));
return bootstrap;
}
@Provides
@Singleton
public DatagramChannelFactory getDatagramChannelFatory(@WorkerExecutor Executor worker) {
final DatagramChannelFactory channelFactory = new NioDatagramChannelFactory(worker);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override public void run() {
channelFactory.releaseExternalResources();
}
});
return channelFactory;
}