项目结构
-
首先是服务器启动类,老生常谈了
/** * @author sss * 服务器启动类 */ public class EchoServer { private final int port; private Logger log = LoggerFactory.getLogger(this.getClass()); public EchoServer(int port) { this.port=port; } //启动服务器 public void start() throws Exception{ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .localAddress(new InetSocketAddress(port)) .childOption(ChannelOption.SO_KEEPALIVE, true) //2小时没有信息流则开启 .option(ChannelOption.SO_BACKLOG, 1024) .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //ch.pipeline().addLast(new ReadTimeoutHandler(5)); //5秒没有读事件就关掉 //ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8)); ch.pipeline().addLast(new MyDecoder()); //自定义的解码 ch.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8)); ch.pipeline().addLast(new TcpHandler()); } }); ChannelFuture f=b.bind().sync(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
2、 重写decoder
public class MyDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
String HEXES = "0123456789ABCDEF";
byte[] req = new byte[msg.readableBytes()];
msg.readBytes(req);
final StringBuilder hex = new StringBuilder(2 * req.length);
for (int i = 0; i < req.length; i++) {
byte b = req[i];
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
out.add(hex.toString());
}
}
-
使用
@ChannelHandler.Sharable public class TcpHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{ Channel incoming = ctx.channel(); String body = (String)msg; System.out.println("原始报文-------" + incoming.remoteAddress().toString()+ "----" + body); long dec_num = Long.parseLong(body, 16); MyTools myTools=new MyTools(); myTools.writeToClient("1002050a840336010102328002021003",ctx,"测试"); } }
-
数据处理
public class MyTools { //十六进制字符转十进制 public int covert(String content){ int number=0; String [] HighLetter = {"A","B","C","D","E","F"}; Map<String,Integer> map = new HashMap<>(); for(int i = 0;i <= 9;i++){ map.put(i+"",i); } for(int j= 10;j<HighLetter.length+10;j++){ map.put(HighLetter[j-10],j); } String[]str = new String[content.length()]; for(int i = 0; i < str.length; i++){ str[i] = content.substring(i,i+1); } for(int i = 0; i < str.length; i++){ number += map.get(str[i])*Math.pow(16,str.length-1-i); } return number; } public byte[] hexString2Bytes(String src) { int l = src.length() / 2; byte[] ret = new byte[l]; for (int i = 0; i < l; i++) { ret[i] = (byte) Integer .valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue(); } return ret; } public void writeToClient(final String receiveStr, ChannelHandlerContext channel, final String mark) { try { ByteBuf bufff = Unpooled.buffer();//netty需要用ByteBuf传输 bufff.writeBytes(hexString2Bytes(receiveStr));//对接需要16进制 channel.writeAndFlush(bufff).addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { StringBuilder sb = new StringBuilder(); if(!StringUtils.isEmpty(mark)){ sb.append("【").append(mark).append("】"); } if (future.isSuccess()) { System.out.println(sb.toString()+"回写成功"+receiveStr); } else { System.out.println(sb.toString()+"回写失败"+receiveStr); } } }); } catch (Exception e) { e.printStackTrace(); System.out.println("调用通用writeToClient()异常"+e.getMessage()); } } }
-
帮初学者添上Application
@SpringBootApplication public class DemoApplication implements CommandLineRunner { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } @Override public void run(String... strings) throws Exception { EchoServer echoServer = new EchoServer(7000); echoServer.start(); } }
很简单的。祝大家学习愉快。