java echo server_分别使用Java IO、NIO、Netty实现的一个Echo Server示例

本文介绍了如何使用Java IO、NIO和Netty实现Echo Server,展示不同方式处理客户端连接和数据传输的过程。通过示例代码,强调了Java IO的线程消耗、NIO的事件驱动以及Netty的易用性优势。
摘要由CSDN通过智能技术生成

分别使用Java IO、Java NIO、Netty来实现一个简单的EchoServer(即原样返回客户端的输入信息)。

Java IO

int port = 9000;

ServerSocket ss = new ServerSocket(port);

while (true) {

final Socket socket = ss.accept();

new Thread(new Runnable() {

public void run() {

while (true) {

try {

BufferedInputStream in = new BufferedInputStream(

socket.getInputStream());

byte[] buf = new byte[1024];

int len = in.read(buf); // read message from client

String message = new String(buf, 0, len);

BufferedOutputStream out = new BufferedOutputStream(

socket.getOutputStream());

out.write(message.getBytes()); // echo to client

out.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}).start();

}

实际效果用telnet来演示,如下所示:

$ telnet 127.0.0.1 9000

Trying 127.0.0.1...

Connected to 127.0.0.1.

Escape character is '^]'.

hi

hi

你好

你好

java io缺点:

需要为每个客户端连接创建一个线程。

Java NIO

ServerSocketChannel ssChannel = ServerSocketChannel.open();

int port = 9001;

ssChannel.bind(new InetSocketAddress(port));

Selector selector = Selector.open();

ssChannel.configureBlocking(false);

ssChannel.register(selector, SelectionKey.OP_ACCEPT); //注册监听连接请求

while (true) {

selector.select();//阻塞 直到某个channel注册的事件被触发

Set keys = selector.selectedKeys();

for (SelectionKey key : keys) {

if (key.isAcceptable()) { //客户端连接请求

ServerSocketChannel ssc = (ServerSocketChannel) key

.channel();

SocketChannel sc = ssc.accept();

sc.configureBlocking(false);

sc.register(selector, SelectionKey.OP_READ); //注册监听客户端输入

}

if(key.isReadable()){ //客户端输入

SocketChannel sc = (SocketChannel) key.channel();

ByteBuffer buffer = ByteBuffer.allocate(1024);

sc.read(buffer);

buffer.flip();

sc.write(buffer);

}

}

keys.clear();

}

优点:

事件驱动  可通过一个线程来管理多个连接(channel)

但要注意 并不是任何场景都是NIO优于IO的。

Netty

public class NettyEchoServer {

public class EchoServerHandler extends ChannelHandlerAdapter {

@Override

public void channelRead(ChannelHandlerContext ctx, Object msg) { //ehco to client

ctx.write(msg);

ctx.flush();

}

@Override

public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

// Close the connection when an exception is raised.

cause.printStackTrace();

ctx.close();

}

}

private int port;

public NettyEchoServer(int port) {

this.port = port;

}

public void run() throws Exception {

EventLoopGroup bossGroup = new NioEventLoopGroup();

EventLoopGroup workerGroup = new NioEventLoopGroup();

try {

ServerBootstrap b = new ServerBootstrap();

b.group(bossGroup, workerGroup)

.channel(NioServerSocketChannel.class)

.childHandler(new ChannelInitializer() {

@Override

public void initChannel(SocketChannel ch)

throws Exception {

ch.pipeline().addLast(

new EchoServerHandler());

}

}).option(ChannelOption.SO_BACKLOG, 128)

.childOption(ChannelOption.SO_KEEPALIVE, true);

// Bind and start to accept incoming connections.

ChannelFuture f = b.bind(port).sync();

// Wait until the server socket is closed.

// In this example, this does not happen, but you can do that to gracefully shut down your server.

f.channel().closeFuture().sync();

} finally {

workerGroup.shutdownGracefully();

bossGroup.shutdownGracefully();

}

}

public static void main(String[] args) throws Exception {

int port = 9002;

new NettyEchoServer(port).run();

}

}

上例摘自官方文档。

优点:

事件驱动的概念比NIO更直观 似乎仅需要继承ChannelHandlerAdapter, 然后覆盖相应方法即可。

参考文档:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值