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