我是socket编程和Netty框架的新手。我试图修改Echo Server example,以便在收到消息后不立即从客户端发送消息,但是来自另一个线程的调用将触发客户端向服务器发送消息。
问题是,除非客户端从readChannel或MessageReceived或channelActive发送消息,否则服务器不会收到消息,这是使用参数(ChannelHandlerContext)指定服务器的位置。我无法找到一种方法来保存服务器通道并稍后重复发送消息。
这是我的客户端处理程序代码;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
public class EchoClientHandler extends ChannelHandlerAdapter {
ChannelHandlerContext server;
@Override
public void channelActive(ChannelHandlerContext ctx) {
this.server = ctx;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
// ctx.write(msg); //not
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//ctx.flush();
}
public void externalcall(String msg) throws Exception {
if(server!=null){
server.writeAndFlush("[" + "] " + msg + '\n');
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
ctx.close();
}
}
当Client创建处理程序时,它还会创建一个带有“SourceGenerator”对象的线程,该对象将处理程序作为参数,以便调用externalcall()方法。
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
/**
* 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, int firstMessageSize) {
this.host = host;
this.port = port;
}
public void run() throws Exception {
// Configure the client.
EventLoopGroup group = new NioEventLoopGroup();
final EchoClientHandler x = new EchoClientHandler();
SourceGenerator sg = new SourceGenerator(x);
new Thread(sg).start();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY, true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(x);
}
});
// Start the client.
ChannelFuture f = b.connect(host, port).sync();
// Wait until the connection is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down the event loop to terminate all threads.
group.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + EchoClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new EchoClient(host, port, firstMessageSize).run();
}
}
和SourceGenerator类;
public class SourceGenerator implements Runnable {
public String dat;
public EchoClientHandler asd;
public SourceGenerator(EchoClientHandler x) {
asd = x;
System.out.println("initialized source generator");
dat = "";
}
@Override
public void run() {
try{
while(true){
Thread.sleep(2000);
dat += "a";
asd.externalcall(dat);
System.out.print("ha!");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
提前致谢!
答案 0 :(得分:1)
如果您想撰写String
,则需要StringEncoder
中的ChannelPipeline
。
否则您只能发送ByteBuf
个实例。