Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java、Netty、TCP和UDP连接集成:没有可用于UDP连接的缓冲区空间_Java_Sockets_Tcp_Udp_Netty - Fatal编程技术网

Java、Netty、TCP和UDP连接集成:没有可用于UDP连接的缓冲区空间

Java、Netty、TCP和UDP连接集成:没有可用于UDP连接的缓冲区空间,java,sockets,tcp,udp,netty,Java,Sockets,Tcp,Udp,Netty,我有一个同时使用TCP和UDP协议的应用程序。主要假设是客户端通过TCP协议连接到服务器,当连接建立时,UDP数据报正在发送。 我必须支持两种连接到服务器的方案: -客户端在服务器运行时连接 -客户端在服务器关闭时连接,并重试连接,直到服务器再次启动 对于第一个场景,一切都运行得很好:两个连接都正常工作。 问题在于第二种情况。当客户端多次尝试通过TCP连接并最终连接时,UDP连接函数会引发异常: java.net.SocketException: No buffer space availabl

我有一个同时使用TCP和UDP协议的应用程序。主要假设是客户端通过TCP协议连接到服务器,当连接建立时,UDP数据报正在发送。 我必须支持两种连接到服务器的方案: -客户端在服务器运行时连接 -客户端在服务器关闭时连接,并重试连接,直到服务器再次启动

对于第一个场景,一切都运行得很好:两个连接都正常工作。 问题在于第二种情况。当客户端多次尝试通过TCP连接并最终连接时,UDP连接函数会引发异常:

java.net.SocketException: No buffer space available (maximum connections reached?): bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:344)
at sun.nio.ch.DatagramChannelImpl.bind(DatagramChannelImpl.java:684)
at sun.nio.ch.DatagramSocketAdaptor.bind(DatagramSocketAdaptor.java:91)
at io.netty.channel.socket.nio.NioDatagramChannel.doBind(NioDatagramChannel.java:192)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:484)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1080)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:430)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:415)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:903)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:197)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:350)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:380)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:116)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
at java.lang.Thread.run(Thread.java:722)
当我在不使用服务器的情况下重新启动客户端应用程序时,客户端将连接到任何问题

什么会导致问题

在下面我附上了类的源代码。所有源代码都来自官方Netty项目页面中的示例。我唯一已经midified的是,我用非静态变量和函数替换了静态变量和函数。这是因为在将来,我将需要许多TCP-UDP连接到多个服务器

public final class UptimeClient {
static final String HOST = System.getProperty("host", "192.168.2.193");
static final int PORT = Integer.parseInt(System.getProperty("port", "2011"));
static final int RECONNECT_DELAY = Integer.parseInt(System.getProperty("reconnectDelay", "5"));
static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));

private static UptimeClientHandler handler;

public void runClient() throws Exception {
    configureBootstrap(new Bootstrap()).connect();
}

private Bootstrap configureBootstrap(Bootstrap b) {
    return configureBootstrap(b, new NioEventLoopGroup());
}

@Override
protected Object clone() throws CloneNotSupportedException {
    return super.clone(); //To change body of generated methods, choose Tools | Templates.
}

Bootstrap configureBootstrap(Bootstrap b, EventLoopGroup g) {
    if(handler == null){
            handler = new UptimeClientHandler(this);
    }
    b.group(g)
     .channel(NioSocketChannel.class)
     .remoteAddress(HOST, PORT)
     .handler(new ChannelInitializer<SocketChannel>() {
        @Override
        public void initChannel(SocketChannel ch) throws Exception {
            ch.pipeline().addLast(new IdleStateHandler(READ_TIMEOUT, 0, 0), handler);
        }
     });

    return b;
}

void connect(Bootstrap b) {
    b.connect().addListener(new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.cause() != null) {
                handler.startTime = -1;
                handler.println("Failed to connect: " + future.cause());
            }
        }
    });
}
}


@Sharable
public class UptimeClientHandler extends SimpleChannelInboundHandler<Object> {
UptimeClient client;
public UptimeClientHandler(UptimeClient client){
    this.client = client;
}
long startTime = -1;

@Override
public void channelActive(ChannelHandlerContext ctx) {
    try {
        if (startTime < 0) {
            startTime = System.currentTimeMillis();
        }
        println("Connected to: " + ctx.channel().remoteAddress());
        new QuoteOfTheMomentClient(null).run();
    } catch (Exception ex) {
        Logger.getLogger(UptimeClientHandler.class.getName()).log(Level.SEVERE, null, ex);
    }
}

@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
}

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
    if (!(evt instanceof IdleStateEvent)) {
        return;
    }

    IdleStateEvent e = (IdleStateEvent) evt;
    if (e.state() == IdleState.READER_IDLE) {
        // The connection was OK but there was no traffic for last period.
        println("Disconnecting due to no inbound traffic");
        ctx.close();
    }
}

@Override
public void channelInactive(final ChannelHandlerContext ctx) {
    println("Disconnected from: " + ctx.channel().remoteAddress());
}

@Override
public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception {
    println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + 's');

    final EventLoop loop = ctx.channel().eventLoop();
    loop.schedule(new Runnable() {
        @Override
        public void run() {
            println("Reconnecting to: " + UptimeClient.HOST + ':' + UptimeClient.PORT);
            client.connect(client.configureBootstrap(new Bootstrap(), loop));
        }
    }, UptimeClient.RECONNECT_DELAY, TimeUnit.SECONDS);
}

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

void println(String msg) {
    if (startTime < 0) {
        System.err.format("[SERVER IS DOWN] %s%n", msg);
    } else {
        System.err.format("[UPTIME: %5ds] %s%n", (System.currentTimeMillis() - startTime) / 1000, msg);
    }
    }
}

public final class QuoteOfTheMomentClient {

private ServerData config;
public QuoteOfTheMomentClient(ServerData config){
    this.config = config;
}

public void run() throws Exception {


    EventLoopGroup group = new NioEventLoopGroup();
    try {
        Bootstrap b = new Bootstrap();
        b.group(group)
         .channel(NioDatagramChannel.class)
         .option(ChannelOption.SO_BROADCAST, true)
         .handler(new QuoteOfTheMomentClientHandler());

        Channel ch = b.bind(0).sync().channel();

        ch.writeAndFlush(new DatagramPacket(
                Unpooled.copiedBuffer("QOTM?", CharsetUtil.UTF_8),
                new InetSocketAddress("192.168.2.193", 8193))).sync();

        if (!ch.closeFuture().await(5000)) {
            System.err.println("QOTM request timed out.");
        }
    }
    catch(Exception ex)
    {
        ex.printStackTrace();
    }
    finally {
        group.shutdownGracefully();
    }
    }
}

public class QuoteOfTheMomentClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {

@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
    String response = msg.content().toString(CharsetUtil.UTF_8);
    if (response.startsWith("QOTM: ")) {
        System.out.println("Quote of the Moment: " + response.substring(6));
        ctx.close();
    }
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
    cause.printStackTrace();
    ctx.close();
    }
}
公共最终类UptimeClient{
静态最终字符串HOST=System.getProperty(“HOST”,“192.168.2.193”);
静态final int PORT=Integer.parseInt(System.getProperty(“PORT”,“2011”));
静态final int RECONNECT_DELAY=Integer.parseInt(System.getProperty(“reconnectDelay”,“5”));
静态final int READ_TIMEOUT=Integer.parseInt(System.getProperty(“readTimeout”,“10”));
专用静态UptimeClientHandler处理程序;
public void runClient()引发异常{
配置引导(新引导()).connect();
}
专用引导配置引导(引导b){
返回configureBootstrap(b,新的NioEventLoopGroup());
}
@凌驾
受保护对象克隆()引发CloneNotSupportedException{
return super.clone();//若要更改生成的方法体,请选择“工具”“模板”。
}
引导配置引导(引导b,事件循环组g){
if(handler==null){
handler=新的UptimeClientHandler(此);
}
b、 小组(g)
.channel(NioSocketChannel.class)
.remoteAddress(主机、端口)
.handler(新的通道初始值设定项(){
@凌驾
public void initChannel(SocketChannel ch)引发异常{
ch.pipeline().addLast(新的IdleStateHandler(读取超时,0,0),handler);
}
});
返回b;
}
无效连接(引导b){
b、 connect().addListener(新的ChannelFutureListener()){
@凌驾
public void operation complete(ChannelFuture future)引发异常{
if(future.cause()!=null){
handler.startTime=-1;
handler.println(“连接失败:+future.cause());
}
}
});
}
}
@可分享
公共类UptimeClientHandler扩展了SimpleChannelInboundHandler{
UptimeClient客户端;
公共UptimeClient客户端(UptimeClient客户端){
this.client=client;
}
长起始时间=-1;
@凌驾
public void channelActive(ChannelHandlerContext ctx){
试一试{
如果(开始时间<0){
startTime=System.currentTimeMillis();
}
println(“连接到:”+ctx.channel().remoteAddress());
新的QuoteOfTheMomentClient(null).run();
}捕获(例外情况除外){
Logger.getLogger(UptimeClientHandler.class.getName()).log(Level.SEVERE,null,ex);
}
}
@凌驾
public void channelRead0(ChannelHandlerContext ctx,Object msg)引发异常{
}
@凌驾
public void userEventTriggered(ChannelHandlerContext ctx,Object evt){
if(!(IdleStateEvent的evt实例)){
返回;
}
IDLESTATEVENT e=(IDLESTATEVENT)evt;
if(e.state()==IdleState.READER\u IDLE){
//连接正常,但上一时段没有流量。
println(“由于没有入站流量而断开连接”);
ctx.close();
}
}
@凌驾
公共无效通道无效(最终通道HandlerContext ctx){
println(“断开连接:”+ctx.channel().remoteAddress());
}
@凌驾
public void ChannelUnregisted(最终ChannelHandlerContext ctx)引发异常{
println(“睡眠时间:“+UptimeClient.RECONNECT_DELAY+'s”);
最终EventLoop循环=ctx.channel().EventLoop();
loop.schedule(新的Runnable(){
@凌驾
公开募捐{
println(“重新连接到:“+UptimeClient.HOST+”:“+UptimeClient.PORT”);
connect(client.configureBootstrap(new Bootstrap(),loop));
}
},UptimeClient.RECONNECT_DELAY,TimeUnit.SECONDS);
}
@凌驾
公共无效例外情况(ChannelHandlerContext ctx,可丢弃原因){
cause.printStackTrace();
ctx.close();
}
void println(字符串消息){
如果(开始时间<0){
System.err.format(“[服务器关闭]%s%n”,消息);
}否则{
System.err.format(“[UPTIME:%5ds]%s%n”,(System.currentTimeMillis()-startTime)/1000,msg);
}
}
}
公共最终类QuoteOfTheMomentClient{
私有服务器数据配置;
公共QuoteOfTheMomentClient(服务器数据配置){
this.config=config;
}
public void run()引发异常{
EventLoopGroup=new NioEventLoopGroup();
试一试{
引导b=新引导();
b、 组(组)
.channel(NioDatagramChannel.class)
.option(ChannelOption.SO_广播,真)
.handler(新的quoteofhemomentclienthandler());
通道ch=b.bind(0.sync().Channel();
ch.writeAndFlush(新数据包(
未冷却的复制缓冲区(“QOTM?”,CharsetUtil.UTF_8),
新的InetSocketAddress(“192.168.2.193”,8193)).sync();
如果(!ch.closeFuture().等待(5000)){
System.err.println(“QOTM请求超时”);
}
}
捕获(例外情况除外)
{
例如printStackTrace();
}
最后{
group.ShutdownGracely();
}
}
}
公共类QuoteOfTheMomentClientHandler扩展了SIML