在netty中,我们只能写入和接收小于1024字节的数据:我们如何写或接收更多?

Gof*_*ier 8 netty

在处理程序中写入2048字节时,应该调用messageRevieved方法两次以接收所有数据...如何接收2048字节数据

服务器:

public class Server{
    public static void main(String[] args){
        ChannelFactory factory=new NioServerSocketChannelFactory(
            Executors.newCachedThreadPool(),
            Executors.newCachedThreadPool());
        ServerBootstrap bootstrap=new ServerBootstrap(factory);
        bootstrap.setPipelineFactory(new CarPipelineFactory());

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(8989));
    }
}
Run Code Online (Sandbox Code Playgroud)

服务器处理程序:

public class ServerHandler extends SimpleChannelHandler{

    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e){
        byte[] resp=data.getBytes();//data is a String greater than 1024bytes;
        ChannelBuffer buffer=ChannelBuffers.buffer(resp.length);
        buffer.writerBytes(resp);
        e.getChannel().write(buffer);
        buffer.clear();
    }
}
Run Code Online (Sandbox Code Playgroud)

客户:

public class Client{
    public static void main(String[] args){
        ChannelFactory channelFactory=new NioClientSocketChannelFactory(
            Executors.newCachedThreadPool(),
            Executors.newCachedThreadPool());
        ClientBootstrap bootstrap=new ClientBootstrap(channelFactory);
        bootstrap.getPipeline().addLast("handler", new PhoneClientHandler());

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.connect(new InetSocketAddress("127.0.0.1",8181));
    }
}
Run Code Online (Sandbox Code Playgroud)

客户端处理程序:

public class ClientHandler extends SimpleChannelHandler{
    public void messageRecieved(ChannelHandlerContext ctx, ChannelStateEvent e){
        ChannelBuffer buffer=(ChannelBuffer)e.getMessage();
        int size=buffer.readableBytes();
        byte[] bytes=new byte[size];
        buffer.readBytes(bytes);
        buffer.clear();
        System.out.println(new String(bytes));//if the data size>1024,the String will speprate into parts.
    }
}
Run Code Online (Sandbox Code Playgroud)

Ren*_*aud 6

那么你总是可以决定一次写入多少字节,但你绝对不知道接收的时间和字节数(这就是NIO有意义的原因).您需要处理自己的缓冲区以接收所需的固定字节数.为此,您可以使用为此目的而设计的FrameDecoder.

另外,通过将tcpNoDelay设置为true,可以确保数据在发送方套接字缓冲区中不会保持太长时间,因此在物理发送数据之前,它不会等待当前"帧"达到某个临界大小.

如果我理解得很好,你一方面写一下2048字节,但另一方面又没有在messagedReceived事件中收到所有数据?尝试检查这些常见问题:

  • 您的应用程序太早终止,数据尚未到达
  • 您的数据被卡在"sender"的套接字缓冲区中,因为您没有关闭 Channel并且tcpNoDelay选项未设置为true.这导致套接字在发送数据包之前等待一些额外的字节.
  • 你没有读取ChannelBuffer中的所有数据,但是由于某种原因,readerIndex被设置为更远的位置

试着向我们展示你的代码的一部分,它应该让事情变得更容易......

ADDED 17/04/2012

如果我理解你正在尝试将字符串数组编码从发送方传递给接收方.以下是小型重构后的代码:

---------------------------- code --------------------- -------写手:response.size()> 1024bytes

byte[] datas = ((String)msg).getBytes("UTF-8"); //ALWAYS SPECIFY THE ENCODING
ChannelBuffer buffer = ChannelBuffers.wrap(datas); //USE DIRECTLY THE ARRAY
System.out.println(buffer);    //buffer'size>1024 here
channel.write(buffer);
Run Code Online (Sandbox Code Playgroud)

----------------------------收到手:应该收到两次,println()会执行两次

ChannelBuffer buffer = (ChannelBuffer) event.getMessage(); 
System.out.println(buffer)    //buffer'size once 1024,once the remainder size
byte[] datas =buffer.readBytes(buffer.readableBytes()).array()
String msg=new String(datas , "UTF-8"); //BAD IDEA because the bytes sequence of the last UTF-8 char could be uncompleted there
System.out.println(str);
Run Code Online (Sandbox Code Playgroud)

这不是这样做的方法,您应该直接使用包org.jboss.netty.handler.codec.string中StringEncoderStringDecoder.它将为您处理框架问题.如果您仍想调试代码,请使用Netty提供的LoggingHandler.你也真的设置了这个选项:

bootstrap.setOption("tcpNoDelay", true);
Run Code Online (Sandbox Code Playgroud)

在双方的bootstraps?