Java 当我添加ExecutionHandler时,netty服务器似乎被阻止了?

Java 当我添加ExecutionHandler时,netty服务器似乎被阻止了?,java,netty,Java,Netty,场景: 我正在编写一个echo客户端和服务器。正在传输的数据是一个字符串: 客户端对字符串进行编码,并将其发送到服务器。 服务器接收数据,解码字符串,然后对接收到的字符串进行编码,并将其发送回客户端 上述过程将重复100000次。(注意:连接是持久的) 不同的内容: 当我同时运行一台服务器和两台客户机时,一切正常,每个客户机接收100000条消息并正常终止 但是当我在服务器上添加一个ExecutionHandler,然后同时运行一个服务器和两个客户端时,一个客户端永远不会终止,网络流量为零 我现

场景

我正在编写一个echo客户端和服务器。正在传输的数据是一个字符串:

客户端对字符串进行编码,并将其发送到服务器。 服务器接收数据,解码字符串,然后对接收到的字符串进行编码,并将其发送回客户端

上述过程将重复100000次。(注意:连接是持久的)

不同的内容

当我同时运行一台服务器和两台客户机时,一切正常,每个客户机接收100000条消息并正常终止

但是当我在服务器上添加一个ExecutionHandler,然后同时运行一个服务器和两个客户端时,一个客户端永远不会终止,网络流量为零

我现在找不到这个问题的关键点,你能给我一些建议吗

我的代码

字符串编码器,字符串解码器,客户端处理程序,服务器处理程序,客户端主,服务器主

//译码器=======================================================

import java.nio.charset.Charset;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class Dcd extends FrameDecoder {
    public static final Charset cs = Charset.forName("utf8");

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel,
            ChannelBuffer buffer) throws Exception {

        if (buffer.readableBytes() < 4) {
            return null;
        }

        int headlen = 4;
        int length = buffer.getInt(0);
        if (buffer.readableBytes() < length + headlen) {
            return null;
        }

        String ret = buffer.toString(headlen, length, cs);
        buffer.skipBytes(length + headlen);

        return ret;
    }
}
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;

public class Ecd extends OneToOneEncoder {
    @Override
    protected Object encode(ChannelHandlerContext ctx, Channel channel,
            Object msg) throws Exception {
        if (!(msg instanceof String)) {
            return msg;
        }

        byte[] data = ((String) msg).getBytes();

        ChannelBuffer buf = ChannelBuffers.dynamicBuffer(data.length + 4, ctx
                .getChannel().getConfig().getBufferFactory());
        buf.writeInt(data.length);
        buf.writeBytes(data);

        return buf;
    }
}
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo client. It initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public class EchoClientHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoClientHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();
    private final AtomicInteger counter = new AtomicInteger(0);
    private final AtomicLong startTime = new AtomicLong(0);

    private String dd;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler(String data) {
        dd = data;
    }

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
        // Send the first message. Server will not send anything here
        // because the firstMessage's capacity is 0.
        startTime.set(System.currentTimeMillis());

        Channels.write(ctx.getChannel(), dd);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        int i = counter.incrementAndGet();
        int N = 100000;
        if (i < N) {
            e.getChannel().write(e.getMessage());
        } else {
            ctx.getChannel().close();
            System.out.println(N * 1.0
                    / (System.currentTimeMillis() - startTime.get()) * 1000);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

/**
 * Sends one message when a connection is open and echoes back any received data
 * to the server. Simply put, the echo client initiates the ping-pong traffic
 * between the echo client and server by sending the first message to the
 * server.
 */
public class EchoClient {

    private final String host;
    private final int port;

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

    public void run() {
        // Configure the client.
        final ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(new Dcd(), new Ecd(),
                        new EchoClientHandler("abcdd"));
            }
        });

        bootstrap.setOption("sendBufferSize", 1048576);
        bootstrap.setOption("receiveBufferSize", 1048576);
        bootstrap.setOption("tcpNoDelay", true);
        bootstrap.setOption("writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("writeBufferHighWaterMark", 64 * 1024);

        List<ChannelFuture> list = new ArrayList<ChannelFuture>();
        for (int i = 0; i < 1; i++) {
            // Start the connection attempt.
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(
                    host, port));
            // Wait until the connection is closed or the connection
            // attempt
            // fails.
            list.add(future);
        }

        for (ChannelFuture f : list) {
            f.getChannel().getCloseFuture().awaitUninterruptibly();
        }

        // Shut down thread pools to exit.
        bootstrap.releaseExternalResources();
    }

    private static void testOne() {
        final String host = "192.168.0.102";
        final int port = 8000;

        new EchoClient(host, port).run();
    }

    public static void main(String[] args) throws Exception {
        testOne();
    }
}
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo server.
 */
public class EchoServerHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoServerHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        Channels.write(ctx.getChannel(), e.getMessage());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

/**
 * Echoes back any received data from a client.
 */
public class EchoServer {

    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void run() {
        // Configure the server.
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        System.out.println(Runtime.getRuntime().availableProcessors() * 2);

        final ExecutionHandler executionHandler = new ExecutionHandler(
                new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                System.out.println("new pipe");
                return Channels.pipeline(new Dcd(), new Ecd(),
                        executionHandler, new EchoServerHandler());
            }
        });

        bootstrap.setOption("child.sendBufferSize", 1048576);
        bootstrap.setOption("child.receiveBufferSize", 1048576);
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("child.writeBufferHighWaterMark", 64 * 1024);

        // Bind and start to accept incoming connections.
        bootstrap.bind(new InetSocketAddress(port));
    }

    public static void main(String[] args) throws Exception {
        int port = 8000;
        new EchoServer(port).run();
    }
}
//客户端处理程序=======================================================

import java.nio.charset.Charset;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class Dcd extends FrameDecoder {
    public static final Charset cs = Charset.forName("utf8");

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel,
            ChannelBuffer buffer) throws Exception {

        if (buffer.readableBytes() < 4) {
            return null;
        }

        int headlen = 4;
        int length = buffer.getInt(0);
        if (buffer.readableBytes() < length + headlen) {
            return null;
        }

        String ret = buffer.toString(headlen, length, cs);
        buffer.skipBytes(length + headlen);

        return ret;
    }
}
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;

public class Ecd extends OneToOneEncoder {
    @Override
    protected Object encode(ChannelHandlerContext ctx, Channel channel,
            Object msg) throws Exception {
        if (!(msg instanceof String)) {
            return msg;
        }

        byte[] data = ((String) msg).getBytes();

        ChannelBuffer buf = ChannelBuffers.dynamicBuffer(data.length + 4, ctx
                .getChannel().getConfig().getBufferFactory());
        buf.writeInt(data.length);
        buf.writeBytes(data);

        return buf;
    }
}
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo client. It initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public class EchoClientHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoClientHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();
    private final AtomicInteger counter = new AtomicInteger(0);
    private final AtomicLong startTime = new AtomicLong(0);

    private String dd;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler(String data) {
        dd = data;
    }

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
        // Send the first message. Server will not send anything here
        // because the firstMessage's capacity is 0.
        startTime.set(System.currentTimeMillis());

        Channels.write(ctx.getChannel(), dd);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        int i = counter.incrementAndGet();
        int N = 100000;
        if (i < N) {
            e.getChannel().write(e.getMessage());
        } else {
            ctx.getChannel().close();
            System.out.println(N * 1.0
                    / (System.currentTimeMillis() - startTime.get()) * 1000);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

/**
 * Sends one message when a connection is open and echoes back any received data
 * to the server. Simply put, the echo client initiates the ping-pong traffic
 * between the echo client and server by sending the first message to the
 * server.
 */
public class EchoClient {

    private final String host;
    private final int port;

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

    public void run() {
        // Configure the client.
        final ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(new Dcd(), new Ecd(),
                        new EchoClientHandler("abcdd"));
            }
        });

        bootstrap.setOption("sendBufferSize", 1048576);
        bootstrap.setOption("receiveBufferSize", 1048576);
        bootstrap.setOption("tcpNoDelay", true);
        bootstrap.setOption("writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("writeBufferHighWaterMark", 64 * 1024);

        List<ChannelFuture> list = new ArrayList<ChannelFuture>();
        for (int i = 0; i < 1; i++) {
            // Start the connection attempt.
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(
                    host, port));
            // Wait until the connection is closed or the connection
            // attempt
            // fails.
            list.add(future);
        }

        for (ChannelFuture f : list) {
            f.getChannel().getCloseFuture().awaitUninterruptibly();
        }

        // Shut down thread pools to exit.
        bootstrap.releaseExternalResources();
    }

    private static void testOne() {
        final String host = "192.168.0.102";
        final int port = 8000;

        new EchoClient(host, port).run();
    }

    public static void main(String[] args) throws Exception {
        testOne();
    }
}
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo server.
 */
public class EchoServerHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoServerHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        Channels.write(ctx.getChannel(), e.getMessage());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

/**
 * Echoes back any received data from a client.
 */
public class EchoServer {

    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void run() {
        // Configure the server.
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        System.out.println(Runtime.getRuntime().availableProcessors() * 2);

        final ExecutionHandler executionHandler = new ExecutionHandler(
                new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                System.out.println("new pipe");
                return Channels.pipeline(new Dcd(), new Ecd(),
                        executionHandler, new EchoServerHandler());
            }
        });

        bootstrap.setOption("child.sendBufferSize", 1048576);
        bootstrap.setOption("child.receiveBufferSize", 1048576);
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("child.writeBufferHighWaterMark", 64 * 1024);

        // Bind and start to accept incoming connections.
        bootstrap.bind(new InetSocketAddress(port));
    }

    public static void main(String[] args) throws Exception {
        int port = 8000;
        new EchoServer(port).run();
    }
}
//主服务器=======================================================

import java.nio.charset.Charset;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class Dcd extends FrameDecoder {
    public static final Charset cs = Charset.forName("utf8");

    @Override
    protected Object decode(ChannelHandlerContext ctx, Channel channel,
            ChannelBuffer buffer) throws Exception {

        if (buffer.readableBytes() < 4) {
            return null;
        }

        int headlen = 4;
        int length = buffer.getInt(0);
        if (buffer.readableBytes() < length + headlen) {
            return null;
        }

        String ret = buffer.toString(headlen, length, cs);
        buffer.skipBytes(length + headlen);

        return ret;
    }
}
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;

public class Ecd extends OneToOneEncoder {
    @Override
    protected Object encode(ChannelHandlerContext ctx, Channel channel,
            Object msg) throws Exception {
        if (!(msg instanceof String)) {
            return msg;
        }

        byte[] data = ((String) msg).getBytes();

        ChannelBuffer buf = ChannelBuffers.dynamicBuffer(data.length + 4, ctx
                .getChannel().getConfig().getBufferFactory());
        buf.writeInt(data.length);
        buf.writeBytes(data);

        return buf;
    }
}
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo client. It initiates the ping-pong
 * traffic between the echo client and server by sending the first message to
 * the server.
 */
public class EchoClientHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoClientHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();
    private final AtomicInteger counter = new AtomicInteger(0);
    private final AtomicLong startTime = new AtomicLong(0);

    private String dd;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler(String data) {
        dd = data;
    }

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
        // Send the first message. Server will not send anything here
        // because the firstMessage's capacity is 0.
        startTime.set(System.currentTimeMillis());

        Channels.write(ctx.getChannel(), dd);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        int i = counter.incrementAndGet();
        int N = 100000;
        if (i < N) {
            e.getChannel().write(e.getMessage());
        } else {
            ctx.getChannel().close();
            System.out.println(N * 1.0
                    / (System.currentTimeMillis() - startTime.get()) * 1000);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

/**
 * Sends one message when a connection is open and echoes back any received data
 * to the server. Simply put, the echo client initiates the ping-pong traffic
 * between the echo client and server by sending the first message to the
 * server.
 */
public class EchoClient {

    private final String host;
    private final int port;

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

    public void run() {
        // Configure the client.
        final ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                return Channels.pipeline(new Dcd(), new Ecd(),
                        new EchoClientHandler("abcdd"));
            }
        });

        bootstrap.setOption("sendBufferSize", 1048576);
        bootstrap.setOption("receiveBufferSize", 1048576);
        bootstrap.setOption("tcpNoDelay", true);
        bootstrap.setOption("writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("writeBufferHighWaterMark", 64 * 1024);

        List<ChannelFuture> list = new ArrayList<ChannelFuture>();
        for (int i = 0; i < 1; i++) {
            // Start the connection attempt.
            ChannelFuture future = bootstrap.connect(new InetSocketAddress(
                    host, port));
            // Wait until the connection is closed or the connection
            // attempt
            // fails.
            list.add(future);
        }

        for (ChannelFuture f : list) {
            f.getChannel().getCloseFuture().awaitUninterruptibly();
        }

        // Shut down thread pools to exit.
        bootstrap.releaseExternalResources();
    }

    private static void testOne() {
        final String host = "192.168.0.102";
        final int port = 8000;

        new EchoClient(host, port).run();
    }

    public static void main(String[] args) throws Exception {
        testOne();
    }
}
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handler implementation for the echo server.
 */
public class EchoServerHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger
            .getLogger(EchoServerHandler.class.getName());

    private final AtomicLong transferredBytes = new AtomicLong();

    public long getTransferredBytes() {
        return transferredBytes.get();
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
        // Send back the received message to the remote peer.
        transferredBytes.addAndGet(((String) e.getMessage()).length());
        Channels.write(ctx.getChannel(), e.getMessage());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
        // Close the connection when an exception is raised.
        logger.log(Level.WARNING, "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;

/**
 * Echoes back any received data from a client.
 */
public class EchoServer {

    private final int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void run() {
        // Configure the server.
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        System.out.println(Runtime.getRuntime().availableProcessors() * 2);

        final ExecutionHandler executionHandler = new ExecutionHandler(
                new OrderedMemoryAwareThreadPoolExecutor(16, 1048576, 1048576));

        // Set up the pipeline factory.
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                System.out.println("new pipe");
                return Channels.pipeline(new Dcd(), new Ecd(),
                        executionHandler, new EchoServerHandler());
            }
        });

        bootstrap.setOption("child.sendBufferSize", 1048576);
        bootstrap.setOption("child.receiveBufferSize", 1048576);
        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.writeBufferLowWaterMark", 32 * 1024);
        bootstrap.setOption("child.writeBufferHighWaterMark", 64 * 1024);

        // Bind and start to accept incoming connections.
        bootstrap.bind(new InetSocketAddress(port));
    }

    public static void main(String[] args) throws Exception {
        int port = 8000;
        new EchoServer(port).run();
    }
}

我现在找到了原因,这是一项艰苦的工作,但充满了乐趣

添加ExecutionHandler后,消息将包装到可运行任务中,并在ChildExecutor中执行。关键点在于:当执行器几乎退出时,可能会将任务添加到ChildExecutor,然后将被ChildExecutor忽略

我添加了三行代码和一些注释,最后的代码如下所示,现在可以工作了,我应该给作者发邮件吗

private final class ChildExecutor implements Executor, Runnable {
    private final Queue<Runnable> tasks = QueueFactory
            .createQueue(Runnable.class);
    private final AtomicBoolean isRunning = new AtomicBoolean();

    public void execute(Runnable command) {
        // TODO: What todo if the add return false ?
        tasks.add(command);

        if (!isRunning.get()) {
            doUnorderedExecute(this);
        } else {
        }
    }

    public void run() {
        // check if its already running by using CAS. If so just return
        // here. So in the worst case the thread
        // is executed and do nothing
        boolean acquired = false;
        if (isRunning.compareAndSet(false, true)) {
            acquired = true;
            try {
                Thread thread = Thread.currentThread();
                for (;;) {
                    final Runnable task = tasks.poll();
                    // if the task is null we should exit the loop
                    if (task == null) {
                        break;
                    }

                    boolean ran = false;
                    beforeExecute(thread, task);
                    try {
                        task.run();
                        ran = true;
                        onAfterExecute(task, null);
                    } catch (RuntimeException e) {
                        if (!ran) {
                            onAfterExecute(task, e);
                        }
                        throw e;
                    }
                }
                //TODO  NOTE (I added): between here and "isRunning.set(false)",some new tasks maybe added.
            } finally {
                // set it back to not running
                isRunning.set(false);
            }
        }

        //TODO NOTE (I added): Do the remaining works.
        if (acquired && !isRunning.get() && tasks.peek() != null) {
            doUnorderedExecute(this);
        }
    }
}
private final类ChildExecutor实现Executor,Runnable{
专用最终队列任务=队列工厂
.createQueue(Runnable.class);
private final AtomicBoolean isRunning=新的AtomicBoolean();
public void execute(Runnable命令){
//TODO:如果add返回false怎么办?
任务。添加(命令);
如果(!isRunning.get()){
双去甲肾上腺素(本);
}否则{
}
}
公开募捐{
//使用CAS检查它是否已经运行。如果已经运行,请返回
//这里,所以在最坏的情况下,线程
//被处决,什么也不做
布尔值=假;
if(isRunning.compareAndSet(false,true)){
获得性=真实;
试一试{
Thread-Thread=Thread.currentThread();
对于(;;){
最终可运行任务=tasks.poll();
//如果任务为空,我们应该退出循环
如果(任务==null){
打破
}
布尔ran=false;
执行前(线程、任务);
试一试{
task.run();
ran=真;
onAfterExecute(任务,空);
}捕获(运行时异常e){
如果(!ran){
onAfterExecute(任务,e);
}
投掷e;
}
}
//TODO NOTE(我添加了):在这里和“isRunning.set(false)”之间,可能添加了一些新任务。
}最后{
//将其设置为不运行
isRunning.set(false);
}
}
//待办事项(我补充):完成剩余的工作。
if(已获取&&!isRunning.get()&&tasks.peek()!=null){
双去甲肾上腺素(本);
}
}
}

这是一个bug,将在3.4.0.2中修复


请参见

当挂起的客户端/服务器挂起时,是否可以发布挂起的客户端/服务器的线程堆栈?您可以通过jstack实用程序或jvisualvm(JDK)获取它们,或者发送“kill-3 JAVA_-PID”信号,如果您正在运行linux/unix box(请参阅)。我添加了一些登录关键点,服务器上的解码器似乎无法执行“Channels.fireMessageReceived(context,result,remoteAddress)”,因此消息无法到达EchoServerHandler,它丢失了。我正在查找原因。在调用fireMessageReceived期间是否有任何异常?请发邮件给我,谢谢你的帮助。我以前做过这件事,客户机和服务器都在Selector.poll()上被阻塞。这意味着他们都在等待阅读,这似乎是正确的。你需要更多的细节吗?嗨,SirVaulterScoff,也不例外,它在默默地丢失。