当前位置: 首页 > 面试题库 >

Netty客户端到服务器的消息

常翰
2023-03-14
问题内容

这实际上是我在这里的第一篇文章,一段时间以来我一直在试图弄清楚这一点,但是我终于打电话给该旗帜,并将尝试寻求有关此主题的一些帮助。

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

Welcome to the server!

来自客户端的消息是

test

我应该知道我从客户端收到消息,因为它应该回显

[You] test

我确实知道服务器可以看到客户端,并且可以向我提供状态更新,但是由于某种原因我无法向服务器发送消息。现在在此之上提出一个问题…偶然地,我目前正在使用
StringDecoderStringEncoder
作为解码器和编码器…如果您正在制作游戏(这就是我在做的事情),并且您会遇到类似登录信息,玩家动作,世界更新等…发送字符串是实现此目的的最佳方法吗?我知道我对字节流有很多了解,在我的编程课上,我经历了操纵字节流的过程,但我仍然还不能百分百满意它们。如果字节流是这样做的更好/最好的方法,那么有人可以详细解释一下如何操作字节流以能够处理不同的项目。

如前所述,这是客户端中所有内容的开始:

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();
}

ClientHandler:

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();
}
}

ServerChannelHandler:

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);
}
}

ServerPipelineFactory:

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

在编码方面,只有一个处理程序将a转换java.lang.StringByteBuf,这就是它的全部工作。也许是更好的引入处理函数调用LineEncoderLineDecoder以及LineCodec那确实平时工作预计:https://html" target="_blank">github.com/netty/netty/issues/1811



 类似资料:
  • 我正在试用netty,但当我响应时,客户端似乎没有收到我的消息。我使用Java NIO和socketChannel编写了相同的代码,看起来很好。我这样说是因为客户机会记录我发送的任何内容。下面是我的服务器 下面是我的服务器处理程序 } 示例响应: 我正在我的盒子上做一个tcpdump,我看到了我在电线上发送的内容,所以我不确定我做错了什么。而且,几分钟后,这会被记录下来,我不确定我在服务器或服务器

  • 似乎服务器拒绝了wireshark输出中的tls协商,但我从代码中看不出原因。它是基于工作的代码,只是它被否决了,因此我用新的API更新。代码是开始。需要使用真实的证书。有人知道为什么服务器发送tcp FIN,ack吗? 我有以下服务器代码: 23 16.856111 sonymobi_7f:55:af intelcor_25:1d:fc ARP 42 10.1.10.100在84:c7:ea:7

  • 我需要在netty中有一个客户机/服务器通信,用于我的项目目的之一。所以我刚开始用一个handsOn来改进,我正在学习netty,我是一个初学者。 我尝试了一个简单的客户端服务器与Netty聊天。 客户端和服务器正在初始化,我可以看到服务器能够获得用于建立连接的客户端管道,但是当客户端发送消息时,它没有进入ServerAdapterHandler的messageReceived部分。下面是我的源代

  • 在本节中,我们将构建一个完整的的 Netty客 户端和服务器。虽然你可能集中在写客户端是浏览器的基于 Web 的服务,接下来你将会获得更完整了解 Netty 的 API 是如何实现客户端和服务器的。 Figure 2.1.Echo client / server 图中显示了连接到服务器的多个并发的客户端。在理论上,客户端可以支持的连接数只受限于使用的 JDK 版本中的制约。 echo(回声)客户端

  • 在探索和实现Proact设计模式后,遇到了一个问题,即客户端(“C”客户端)连接在限制后不再接受。开始探索netty。这是我试图做的1。C客户端建立连接2。Java服务器接受连接并开始使用TCP向客户端发送8 Mb大小的字节缓冲区。有什么想法吗?netty是一个好的选择吗?我浏览了netty的一个很好的例子,不幸的是不走运。 先谢谢你。 尊敬的Ravi

  • 我有一个Netty客户端和一个Netty服务器,并按照主要教程后,为了有一个EchoClient/服务器,我想让它,使我的客户端发送消息到我的服务器,当他第一次连接到它。 下面是我的的方法,这些方法应该解决这个问题: 但是正如你所看到的,教程使用了一个ByteBuf和一个String似乎不起作用! 下面是我如何在我的方法中显示收到的消息: 但是当为使用并在构造函数中初始化它并发送它时,我的服务器不