netty自定義協議上傳
阿新 • • 發佈:2018-11-09
- 客戶端:
import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public class SocketClient { public static void main(String[] args) throws InterruptedException { EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventLoopGroup) .channel(NioSocketChannel.class) .handler(new LoggingHandler(LogLevel.INFO)) .handler(new SocketClientInitializer()); ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync(); channelFuture.channel().closeFuture().sync(); } finally { eventLoopGroup.shutdownGracefully(); } } }
import io.netty.buffer.ByteBuf; import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.*; public class SocketClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { UnpooledByteBufAllocator allocator = new UnpooledByteBufAllocator(false); ByteBuf buffer = allocator.buffer(20); // String longMsgBody = ""; String device = "T0001"; String imgStr = getBytes(); int length = imgStr.length(); System.out.println("總長度: " + length + device.length() + 8); buffer.writeInt(length + device.length() + 8); // buffer.writeBytes(new byte[]{0x0a, 0x0d}); buffer.writeInt(device.length()); buffer.writeInt(imgStr.length()); buffer.writeBytes(device.getBytes()); buffer.writeBytes(imgStr.getBytes()); ctx.writeAndFlush(buffer); } private static String getBytes() { try { StringBuffer sb = new StringBuffer(); FileInputStream fis = new FileInputStream("D:/mmmm.jpg"); BufferedInputStream bis = new BufferedInputStream(fis); java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream(); byte[] buff = new byte[1024]; int len = 0; while ((len = fis.read(buff)) != -1) { bos.write(buff, 0, len); } // 得到圖片的位元組陣列 byte[] result = bos.toByteArray(); System.out.println(byte2HexStr(result)); // 位元組陣列轉成十六進位制 String str = byte2HexStr(result); // /* // * 將十六進位制串儲存到txt檔案中 // */ // PrintWriter pw = new PrintWriter( // new FileWriter("D:/mmmm.txt")); // pw.println(str); // pw.close(); return str; } catch (IOException e) { e.printStackTrace(); } return ""; } /* * 實現位元組陣列向十六進位制的轉換方法一 */ public static String byte2HexStr(byte[] b) { String hs = ""; String stmp = ""; for (int n = 0; n < b.length; n++) { stmp = (Integer.toHexString(b[n] & 0XFF)); if (stmp.length() == 1) hs = hs + "0" + stmp; else hs = hs + stmp; } return hs.toUpperCase(); } private static byte uniteBytes(String src0, String src1) { byte b0 = Byte.decode("0x" + src0).byteValue(); b0 = (byte) (b0 << 4); byte b1 = Byte.decode("0x" + src1).byteValue(); byte ret = (byte) (b0 | b1); return ret; } /* * 實現位元組陣列向十六進位制的轉換的方法二 */ public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(""); if (src == null || src.length <= 0) { return null; } for (int i = 0; i < src.length; i++) { int v = src[i] & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } }
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; public class SocketClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new SocketClientHandler()); } }
- 服務端
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
public class SocketServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup parentGroup = new NioEventLoopGroup();
EventLoopGroup childGroup = new NioEventLoopGroup();
try {
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(parentGroup, childGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new SocketServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
channelFuture.channel().closeFuture().sync();
}
finally {
parentGroup.shutdownGracefully();
childGroup.shutdownGracefully();
}
}
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import util.Consts;
import java.io.File;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
public class BusinessServerHandler extends ChannelInboundHandlerAdapter {
private static int count = 0;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = (ByteBuf) msg;
Consts.logger.info("BusinessServerHandler接收的二進位制形式指令: " + ByteBufUtil.hexDump(buf));
Consts.logger.info("BusinessServerHandler接收的ASCII形式指令: " + buf.toString(Charset.forName("US-ASCII")));
System.out.println("BusinessServerHandler call count=" + ++count);
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
int total = ByteBuffer.wrap(req, 0, 4).getInt();
int devLength = ByteBuffer.wrap(req, 4, 4).getInt();
int imgLength = ByteBuffer.wrap(req, 8, 4).getInt();
String dev = getString(ByteBuffer.wrap(req, 12, devLength));
String img = getString(ByteBuffer.wrap(req, 12 + devLength, total - 12 - devLength));
Consts.logger.info("裝置號: " + dev);
Consts.logger.info("圖片: " + img);
saveToImgFile(img, "D:/nnnn.jpg");
}
/**
* ByteBuffer 轉換 String
*
* @param buffer
* @return
*/
public static String getString(ByteBuffer buffer) {
Charset charset = null;
CharsetDecoder decoder = null;
CharBuffer charBuffer = null;
try {
charset = Charset.forName("UTF-8");
decoder = charset.newDecoder();
// charBuffer = decoder.decode(buffer);//用這個的話,只能輸出來一次結果,第二次顯示為空
charBuffer = decoder.decode(buffer.asReadOnlyBuffer());
return charBuffer.toString();
} catch (Exception ex) {
ex.printStackTrace();
return "";
}
}
public void saveToImgFile(String src, String output) {
if (src == null || src.length() == 0) {
return;
}
try {
FileOutputStream out = new FileOutputStream(new File(output));
byte[] bytes = src.getBytes();
for (int i = 0; i < bytes.length; i += 2) {
out.write(charToInt(bytes[i]) * 16 + charToInt(bytes[i + 1]));
}
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private int charToInt(byte ch) {
int val = 0;
if (ch >= 0x30 && ch <= 0x39) {
val = ch - 0x30;
} else if (ch >= 0x41 && ch <= 0x46) {
val = ch - 0x41 + 10;
}
return val;
}
}
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import util.Consts;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.List;
/**
* 0a0d 裝置號長度4 圖片長度4 圖片
*/
public class SelfDefineEncodeHandler extends ByteToMessageDecoder {
private static int count = 0;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf bufferIn, List<Object> out) throws Exception {
Consts.logger.info("decode接收的二進位制形式指令: " + ByteBufUtil.hexDump(bufferIn));
Consts.logger.info("decode接收的ASCII形式指令: " + bufferIn.toString(Charset.forName("US-ASCII")));
if (bufferIn.readableBytes() < 10) {
return;
}
int beginIndex = bufferIn.readerIndex();
int length = bufferIn.readInt();
System.out.println("decode call count="+ ++count);
System.out.println("bufferIn.readableBytes()="+bufferIn.readableBytes());
System.out.println("beginIndex="+beginIndex);
if (bufferIn.readableBytes() < length) {
bufferIn.readerIndex(beginIndex);
return;
}
bufferIn.readerIndex(beginIndex + length - 4);
ByteBuf otherByteBufRef = bufferIn.slice(beginIndex, length);
otherByteBufRef.retain();
out.add(otherByteBufRef);
}
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
public class SocketServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new SelfDefineEncodeHandler());
pipeline.addLast(new BusinessServerHandler());
}
}