gpt4 book ai didi

java - Netty 客户端到服务器消息

转载 作者:搜寻专家 更新时间:2023-10-30 21:32:20 26 4
gpt4 key购买 nike

这实际上是我在这里发表的第一篇文章,一段时间以来我一直在努力解决这个问题,但我最终决定加入 flag 并尝试在这个主题上获得一些帮助。

所以我有一个客户端和一个服务器,它们是在回声客户端/服务器和安全聊天客户端/服务器之后建模的。我对聊天的 SSL 部分不感兴趣,使用 echo 只是为了确保我从客户端/服务器获得响应。我将在这篇文章的底部添加所有相关代码。我现在遇到的问题是,我可以在客户端连接时从服务器向客户端发送消息,但是在服务器向客户端发送初始消息后,我无法从客户端向服务器发送消息。从服务器发送的消息是:

Welcome to the server!

客户端的消息是

test

我应该知道我收到了来自客户端的消息,因为它应该回显

[You] test

我知道服务器会看到客户端,它会给我状态更新,但由于某种原因我无法向服务器发送消息。现在问一个关于这个的问题......我目前正在使用 StringDecoderStringEncoder 作为解码器和编码器......如果你正在制作游戏(这就是我正在做的)并且您将拥有诸如登录、玩家移动、世界更新等内容……发送字符串是执行此操作的最佳方式吗?我知道我经常看到字节流,在我的编程课上,我讲过如何操作字节流,但我仍然不是 100% 熟悉它们。如果字节流是执行此操作的更好/最好的方法,那么有人可以详细解释它是如何操作字节流以处理不同项目的。

如前所述,这是客户端中一切的开始:

public class Client {

public Client() {
// Initialize the window
GameWindow.init();
// Initialize the server connection
ClientHandler.init();
}

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

// Set a default server address if one isn't specified in the arguments
if (args.length < 2 || args.length > 3) {
System.err.println("Usage: " + Client.class.getSimpleName() + " <host> <port> [<first message size>]");
System.err.println("Using default values.");
} else {
// Parse arguments
Settings.host = args[0];
Settings.port = Integer.parseInt(args[1]);
}

// start client
new Client();
}

客户端处理程序:

package simple.client.net;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.WriteCompletionEvent;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

import simple.client.Settings;

public class ClientHandler extends SimpleChannelUpstreamHandler {

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

public static Channel channel;

public ClientHandler() {
}

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

// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ClientPipelineFactory());

// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(Settings.host, Settings.port));

// Wait until the connection is closed or the connection attempt fails.
channel = future.awaitUninterruptibly().getChannel();

// This is where the test write is <<------
ChannelFuture test = channel.write("test");

if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return;
}
}

@Override
public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Bound: " + e.getChannel().isBound());
}

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Connected: " + e.getChannel().isConnected());
System.out.println("Connected: " + e.getChannel().getRemoteAddress());
}

@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Closed: " + e.getChannel());
}

@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Disconnected: " + e.getChannel());
}

@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Open: " + e.getChannel().isOpen());
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
System.out.println("Error: " + e.getCause());
}

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
System.out.println("Message: " + e.getMessage());
}
}

最后是 ClientPipeline:

package simple.client.net;

import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

public class ClientPipelineFactory implements ChannelPipelineFactory {

public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = pipeline();

pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ClientHandler());

return pipeline;
}

}

服务器端:

package simple.server;

public class Server {
public static void main(String[] args) throws Exception {
ServerChannelHandler.init();
}
}

服务器 channel 处理器:

package simple.server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.logging.Logger;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
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.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class ServerChannelHandler extends SimpleChannelHandler {

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

private static ChannelGroup channels;
private static ServerBootstrap bootstrap;

public ServerChannelHandler() {
}

/**
* Initialize the Server Channel Handler
*/
public static void init() {
// create a channels group to add incoming channels to
channels = new DefaultChannelGroup();

// create the server bootstrap (fancy word for pre-made server setup)
bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));

// set the server pipeline factory
bootstrap.setPipelineFactory(new ServerPipelineFactory());

// server settings
bootstrap.setOption("keepAlive", true);

// bind the server to the port
bootstrap.bind(new InetSocketAddress(Settings.PORT_ID));
}

@Override
public void channelBound(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Bound: " + e.getChannel());
}

@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Connected: " + e.getChannel());
channels.add(e.getChannel());
e.getChannel().write("Welcome to the test server!\n\r");
}

@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Closed: " + e.getChannel());
}

@Override
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Disconnected: " + e.getChannel());
}

@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.out.println("Open: " + e.getChannel());
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
System.out.println("Error: " + e.getCause());
}

@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
System.out.println("Message: " + e.getMessage());
for (Channel c : channels) {
if (e.getMessage().equals("shutdown")) {
shutdown();
}
if (c != e.getChannel()) {
c.write("[" + e.getChannel().getRemoteAddress() + "] " + e.getMessage() + "\n\r");
} else {
c.write("[You] " + e.getMessage() + "\n\r");
}
}
}

/**
* Shuts down the server safely
*/
public static final void shutdown() {
channels.close();
bootstrap.releaseExternalResources();
System.exit(0);
}
}

服务器管道工厂:

package simple.server;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

import simple.server.decoder.Decoder;
import simple.server.encoder.Encoder;

public class ServerPipelineFactory implements ChannelPipelineFactory {
@Override
public ChannelPipeline getPipeline() throws Exception {
ChannelPipeline pipeline = Channels.pipeline();

pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("handler", new ServerChannelHandler());

return pipeline;
}
}

再一次感谢大家在理解这一点上能给我的任何帮助。

最佳答案

您忘记将 \r\n 附加到 "test"。它应该是:channel.write("test\r\n").`

从管道中可以看出,解码部分由两个处理程序组成。第一个将接收到的数据拆分并合并到一行字符串中,并去除以它结尾的行。第二个将单行字符串转换为 java.lang.String

在编码方面,只有一个处理程序,它将 java.lang.String 转换为 ByteBuf,仅此而已。也许最好引入一个名为 LineEncoderLineDecoderLineCodec 的处理程序来完成通常预期的工作:https://github.com/netty/netty/issues/1811

关于java - Netty 客户端到服务器消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13923032/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com