java Netty - 客户端/服务器聊天
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30074831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Netty - Client/Server chat
提问by Praveen
I need to have a client/server communication in netty for one of my project purpose. So I just started with a handsOn to improve from that.I am learning netty and I am a beginner in that.
为了我的项目目的之一,我需要在 netty 中进行客户端/服务器通信。所以我刚开始动手改进。我正在学习 netty,我是初学者。
I have tried a simple client server chatting with netty.
我尝试过一个简单的客户端服务器与 netty 聊天。
The client and server is getting initialized and I could see the server is able to get the Client pipeline for connection establishment, but when the client sends the message, it is not getting inside the messageReceived part of the ServerAdapterHandler. Below are my source codes,
客户端和服务器正在初始化,我可以看到服务器能够获取用于建立连接的客户端管道,但是当客户端发送消息时,它没有进入 ServerAdapterHandler 的 messageReceived 部分。下面是我的源代码,
CLIENT:
客户:
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
public class ContainerClient {
String server;
int port;
int containerPort;
public ContainerClient(String server, int port, int containerPort) {
this.server = server;
this.port = port;
this.containerPort = containerPort;
}
public static void main(String[] args) {
String server = "localhost";
int port = 5252;
int containerPort = 8094;
new ContainerClient(server, port, containerPort).start();
}
public void start() {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap().group(group)
.channel(NioSocketChannel.class)
.handler(new ClientAdapterInitializer());
Channel channel = bootstrap.connect(server, port).sync().channel();
channel.write("Hi\n");
channel.write("Hi\n");
channel.write("Hi\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
}
CLIENT CHANNEL INITIALIZER:
客户端通道初始化器:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ClientAdapterInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ClientAdapterHandler());
}
}
CLIENT MESSAGE HANDLER:
客户端消息处理程序:
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
public class ClientAdapterHandler extends
ChannelInboundMessageHandlerAdapter<String> {
@Override
public void messageReceived(ChannelHandlerContext context, String message)
throws Exception {
System.out.println(message);
if (message.equals("quit"))
throw new ServerEndedException("Server is closed");
}
@Override
public void channelRead(ChannelHandlerContext arg0, Object arg1)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void channelReadComplete(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
}
}
SERVER:
服务器:
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class ContainerServer {
int port;
public static void main(String[] args) {
new ContainerServer().start();
}
public void start() {
port = 5252;
EventLoopGroup producer = new NioEventLoopGroup();
EventLoopGroup consumer = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap()
.group(producer, consumer)
.channel(NioServerSocketChannel.class)
.childHandler(new ServerAdapterInitializer());
System.out.println("Server started");
bootstrap.bind(port).sync().channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
producer.shutdownGracefully();
consumer.shutdownGracefully();
}
}
}
SERVER CHANNEL INITIALIZER:
服务器通道初始化器:
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ServerAdapterHandler());
}
}
SERVER MESSAGE HANDLER:
服务器消息处理程序:
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
public class ServerAdapterHandler extends
ChannelInboundMessageHandlerAdapter<String> {
private static final ChannelGroup channels = new DefaultChannelGroup(
"containers", GlobalEventExecutor.INSTANCE);
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("[START] New Container has been initialzed");
channels.add(ctx.channel());
super.handlerAdded(ctx);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
System.out.println("[END] A Container has been removed");
channels.remove(ctx.channel());
super.handlerRemoved(ctx);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, String arg1)
throws Exception {
Channel currentChannel = ctx.channel();
System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - "
+ arg1);
currentChannel.write("[Server] - Success");
}
@Override
public boolean beginMessageReceived(ChannelHandlerContext ctx)
throws Exception {
System.out.println("Message received");
return super.beginMessageReceived(ctx);
}
@Override
public void channelRead(ChannelHandlerContext arg0, Object arg1)
throws Exception {
System.out.println("channelRead");
}
@Override
public void channelReadComplete(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
System.out.println("channelReadComplete");
}
@Override
public void channelWritabilityChanged(ChannelHandlerContext arg0)
throws Exception {
// TODO Auto-generated method stub
System.out.println("channelWritabilityChanged");
}
}
Below is the output I am getting in server and nothing in client:
以下是我在服务器中获得的输出,而在客户端中没有任何输出:
Server started
[START] New Container has been initialzed
channelReadComplete
[END] A Container has been removed
But The expected should be,
但预期应该是,
Server started
[START] New Container has been initialzed
channelReadComplete
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[END] A Container has been removed
And I should get response in client as,
我应该得到客户的回应,
[Server] - Success
[Server] - Success
[Server] - Success
I tried with line Delimter in framer also, but same results.
我也尝试在成帧器中使用 line Delimter,但结果相同。
Someone could you please help on this?
有人可以帮忙吗?
Thanks in advance!!.
提前致谢!!。
采纳答案by Moh-Aw
It works for me with the following change to the start
method in your ContainerClient
. Just add a channel.flush()
.
它对我有用,对start
您的ContainerClient
. 只需添加一个channel.flush()
.
public void start() {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ClientAdapterInitializer());
Channel channel = bootstrap.connect(server, port).sync().channel();
channel.write("Hi\n");
channel.write("Hi\n");
channel.write("Hi\n");
channel.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
group.shutdownGracefully();
}
}
The ChannelInboundMessageHandlerAdapter
does not exist anymore in newer version of 4.0. I used a SimpleChannelInboundHandler
.
将ChannelInboundMessageHandlerAdapter
在4.0新版本已经不存在了。我用了一个SimpleChannelInboundHandler
.
public class ServerAdapterHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel currentChannel = ctx.channel();
System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - " + msg);
currentChannel.write("[Server] - Success");
}
}