java socket与Netty服务器通信
本人初学java,第一次学写技术博客:
ByteBuffer与ByteBuf
C/C++中在进行网络通信的过程中直接面对的是字节流或是字符流。java中网络通信的话面对的是缓冲区buffer。
ByteBuffer是来自于java.nio
ByteBuf是来自于io.netty.buffer 两者相互转换自然是可以的。ByteBuf的nioBuffer()方法可以得到ByteBuf对应的ByteBuffer.
使用ByteBuffer与Netty通信
在ByteBuffer 开始写入需要传输数据的大小
应用的背景是通过Socket 将一个自定义类传输到服务器,在服务器正确解析出这个类。
在传输的ByteBuffer的开始四字节存储要传输byte数组的长度,再将要传输的byte数组放入ByteBuffer中。
在接收端的相应的要在pipeline中加入两个处理函数
LengthFieldBasedFrameDecoder() LengthFieldPrepender()
客户端
if(socket == null)
socket = new Socket(host, port);
OutputStream out = socket.getOutputStream();
ByteBuffer header = ByteBuffer.allocate(4);
header.putInt(socksend.length);
out.write(header.array());
out.write(socksend);
out.flush();
服务器
ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4));
ch.pipeline().addLast(new CsDecoder());
ch.pipeline().addLast(new CBgHandler());
socksend是自定义类转换成的byte数组,
CsDecoder()是在服务器端将收到的数据转换成自定义类
ByteBuffer 写入数据后调用flip()函数
写看代码
if(socket == null)
socket = new Socket(host, port);
OutputStream out = socket.getOutputStream();
ByteBuffer header = ByteBuffer.allocate(1024);
header.clear();
header.put(socksend);
header.flip();
out.write(header.array());
out.flush();
ch.pipeline().addLast(new CsDecoder());
ch.pipeline().addLast(new CBgHandler());
直接讲数据写入ByteBuffer并且不调用flip()方法的话,服务器接收到数据总是无法解析。
因为ByteBuffer中有一个position和limit,在写入数据的过程中position不断增加,limit是ByteBuffer的最大容量。在读取ByteBuffer时是从position到limit的数据。所以flip()函数的作用就是在数据写完后将position置为0,limit置为写入字节的数量,这样ByteBuffer才能正确的du’ru。
使用ByteBuf与Netty通信
因为ByteBuf是Netty内部实现的类,所以可以和Netty无缝衔接实现起来自然方便很多。
客户端
if(socket == null)
socket = new Socket(host, port);
OutputStream out = socket.getOutputStream();
ByteBuf header = Unpooled.buffer(1024);
header.writeBytes(pbdata);
out.write(header.array());
out.flush();
服务器
ch.pipeline().addLast(new CsDecoder());
ch.pipeline().addLast(new CBgHandler());