最近写了个基于TCP/IP 协议的 小程序

最近用 netty 做了个接收数据的小程序

我的目录结构如下:在这里插入图片描述
我的myabtis配置文件
在这里插入图片描述
基础类存储报文体 里面添加 set get方法
在这里插入图片描述
基础类存储报文头 面添加 set get方法
在这里插入图片描述
mapper接口 我是图方便 跟 mapper.xml 放在了一起
在这里插入图片描述
mapper.xml

在这里插入图片描述
ObjBootstrap类

package com.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.apache.log4j.Logger;

public class ObjBootstrap {

private  static final Logger log= Logger.getLogger(ObjBootstrap.class);

/**
 * 启动方法
 */
public static void action(){
    //初始化netty服务器
    ServerBootstrap bootstrap=new ServerBootstrap();

    //IO线程
    // 系统Task:通过调用 NioEventLoop的 execute(Runnable task)方法实现,Netty有很多系统Task,创建它们的主要原因是:
    // 当IO线程和用户线程同时操作网络资源时,为了防止并发操作导致的锁竞争,将用户线程的操作封装成Task放入消息队列中,
    // 由IO线程负责执行,这样就实现了局部无锁化

    //定时任务:通过调用 NioEventLoop的 schedule(Runnable command, long delay,TimeUnit unit)方法实现。
    //正是因为 NioEventLoop具备多种职责,所以它的实现比较特殊,它并不是个简单的Runnable

// NioEventLoopGroup 是 NioEventLoop的容器 线程组
NioEventLoopGroup loop=new NioEventLoopGroup();
//绑定线程组
//设定通讯模式NIO 非阻塞模式
bootstrap.group(loop)
.channel(NioServerSocketChannel.class)
.localAddress(“0.0.0.0”,2020)
.childHandler(new ChannelInitializer() {

// 初始化管道
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {

                    //控制器
                    log.info(" receive data - controller");
                    socketChannel.pipeline().addLast(new PersonHandler());
                }
            });

// 异步执行
ChannelFuture sync = null;
try {
sync = bootstrap.bind().sync();
} catch (InterruptedException e) {
log.info("sync error === "+e.getMessage());
e.printStackTrace();
}
System.out.println(“ObjBootstrap–>bootstrap.bind().sync() start success!”);
log.info(“ObjBootstrap–>bootstrap.bind().sync() start success!”);
///ChannelFuture sync():等待,直到异步操作执行完毕,核心思想同await。我们得到Future实例后,
// 可以使用sync()方法来阻塞当前线程,直到异步操作执行完毕。和await的区别为,如果异步操作失败,
// 那么将会重新抛出异常(将上述cause()方法中的异常抛出)。await和sync一样,
// 当异步操作执行完毕后,通过notifyAll()唤醒。
/
try {
sync.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
log.info("异步执行结束出现异常 === "+e.getMessage());
}
}

}

PersonHandler.java

package com.server;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import org.apache.log4j.Logger;
import java.util.Date;
import static com.util.Handle_data.handle_data;

public class PersonHandler extends ChannelInboundHandlerAdapter {

private  static final Logger log= Logger.getLogger(PersonHandler.class);

//这里我们可以读取客户端发送的消息
/*
1.ChannelHandlerContext ctx:上下文对象,含有管道pipline,通道channel,地址
2.Object msg默认是客户端发送的消息,默认Object
 */
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    String revive;
    //将msg转成byteBuf
    ByteBuf byteBuf = (ByteBuf) msg;

// System.out.println(“客户端发送消息是===========” + byteBuf.toString(CharsetUtil.UTF_8));
log.info(“client发送消息是===========” + byteBuf.toString(CharsetUtil.UTF_8));
// System.out.println(“客 户 端地 址 是===========” + ctx.channel().remoteAddress());
log.info(“client ip===========” + ctx.channel().remoteAddress());
Date date = new Date();
// System.out.println(" ---- START ----" + String.format("%tY-%tm-%td-%tH:%tM:%tS", new Object[]{date, date, date, date, date, date}));
log.info(" ---- START ----" + String.format("%tY-%tm-%td-%tH:%tM:%tS", new Object[]{date, date, date, date, date, date}));
revive = byteBuf.toString(CharsetUtil.UTF_8);
handle_data(revive);
Date date1 = new Date();
// System.out.println(" ---- END ----" + String.format("%tY-%tm-%td-%tH:%tM:%tS", new Object[]{date1, date1, date1, date1, date1, date1}));
// System.out.println(“数据处理已完成”);
log.info(" ---- END ----" + String.format("%tY-%tm-%td-%tH:%tM:%tS", new Object[]{date1, date1, date1, date1, date1, date1}));
log.info(“数据处理已完成”);
}

//数据读取完毕
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
    //writeAndFlush是write方法+Flush方法,将数据写入到缓存并刷新
    //一般来讲我们对发送的数据进行编码
    ctx.writeAndFlush(Unpooled.copiedBuffer("Hello客户端", CharsetUtil.UTF_8));
    log.info("读取数据完毕");
}

//处理异常,一般是需要关闭通道
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    log.error(cause.getMessage());
    log.error("数据处理异常,关闭通道");
    ctx.close();
}

}

ServerStart.java

package com.server;

import org.apache.log4j.Logger;
import static com.server.ObjBootstrap.action;
public class ServerStart {
private static final Logger log= Logger.getLogger(ServerStart.class);

public static void main(String[] args) {

    Runnable runnable = new Runnable() {
        public void run() {
            try {
                action();
            }  catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    Thread thread = new Thread(runnable);
    thread.start();
}

}

大家如果有什么更好的实现方式或者 我写的有不对的地方 希望指正 。

对了!最近因为程序插入前半部分数据后成功,后半部分的数据插入失败的问题 ,我是在下面的地方添加了 logger日志才最终找到问题,所以希望大家再做程序时 多添加日志,这样事半功倍!!
在这里插入图片描述

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页