Mina封装好了很完善的方法,代码注释的很清楚直接上代码:
// 创建一个非阻塞的Server端socket,用NIO IoAcceptor acceptor = new NioSocketAcceptor(); // 创建接受数据的过滤器, 处理最简单的字符串传输,Mina 已经为我们提供了 TextLineCodecFactory // 编解码器工厂来对字符串进行编解码处理。 acceptor.getFilterChain().addLast("logger", new LoggingFilter()); // 设定这个过滤器将一行一行的读取数据 acceptor.getFilterChain().addLast("codec", new ProtocolCodecFilter(new SocketCodecFactory())); // 然后我们把这个IoHandler 注册到IoService: acceptor.setHandler(new TimeServerHandler()); // 设置读取数据的缓冲区大小 acceptor.getSessionConfig().setReadBufferSize(2048); // 设置10没有消息就进入闲置状态 acceptor.getSessionConfig().setIdleTime(IdleStatus.BOTH_IDLE, 10); // 绑定端口号 acceptor.bind(new InetSocketAddress(Constant.PORT_NUMBER));虽然Mina自己有自己的解码工厂,为了自己的也无需求一般我们会自己建立自己的解码工厂SocketCodecFactory()
public class SocketCodecFactory implements ProtocolCodecFactory { private final SocketDecode decoder; private final SocketEncode encoder; public SocketCodecFactory() { decoder = new SocketDecode(); encoder = new SocketEncode(); } @Override public ProtocolDecoder getDecoder(IoSession session) throws Exception { return decoder; } @Override public ProtocolEncoder getEncoder(IoSession session) throws Exception { return encoder; } }SocketDecode 这里处理自己的逻辑,根据客户端 发送的数据进行自己业务逻辑操作
public class SocketDecode implements ProtocolDecoder { int bufid = 0; @Override public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception { int playerid = 0; playerid = (int) session.getAttribute("PLAYERID", playerid); if (playerid > 0) { getStutasCode(in); } // 创建房间 并向客户端返回房间信息 if (bufid == 1) { RoomManage.getInstace().create(playerid); } // 玩家进入房间 并向客户端返回所有玩家信息 if (bufid == 2) { PBPlayer playerBuf = PBPlayer.parseFrom(in.array()); RoomManage.getInstace().enter(playerBuf.getRoomId(), new Player(playerBuf.getPlayerId(), playerBuf.getName(), playerBuf.getHeadurl(), playerBuf.getGender(), playerBuf.getScore(), session)); } // 玩家坐下 if (bufid == 3) { PBPlayer playerBuf = PBPlayer.parseFrom(in.array()); PBSeat pbSeat = PBSeat.parseFrom(in.array()); RoomManage.getInstace().sitDown( playerBuf.getRoomId(), new Player(playerBuf.getPlayerId(), playerBuf.getName(), playerBuf.getHeadurl(), playerBuf.getGender(), playerBuf.getScore(), session), pbSeat.getSeatId()); } // 玩家离开房间 并向客户端返回此房间的所有信息 if (bufid == 3) { PBPlayer playerBuf = PBPlayer.parseFrom(in.array()); RoomManage.getInstace().leave(playerBuf.getRoomId(), new Player(playerBuf.getPlayerId(), session)); } // 开始游戏 if (bufid == 4) { PBRoom pbroom = PBRoom.parseFrom(in.array()); RoomManage.getInstace().roomHashMap.get(pbroom.getRoomId()).begin(); } } private void getStutasCode(IoBuffer in) { UtilsProtobuf.PButil buf = null; try { buf = UtilsProtobuf.PButil.parseFrom(in.array()); } catch (InvalidProtocolBufferException e) { // TODO Auto-generated catch block e.printStackTrace(); } bufid = buf.getCode(); } @Override public void dispose(IoSession session) throws Exception { // TODO Auto-generated method stub } @Override public void finishDecode(IoSession session, ProtocolDecoderOutput out) throws Exception { // TODO Auto-generated method stub } }里面的逻辑代码是我鞋的简单需求,以供以后查看便于阅读 SocketEncode 当服务端需要向客户端回复消息的时候回走到这个类(out.write(messsage))
public class SocketEncode implements ProtocolEncoder { @Override public void dispose(IoSession session) throws Exception { // TODO Auto-generated method stub } @Override public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception { out.write(message); } }客户端和服务端Mina基本相同
public class MimaTimeClient { public static void main(String[] args) { IoConnector connector = new NioSocketConnector(); connector.getFilterChain().addLast("logger", new LoggingFilter()); connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new PrefixedStringCodecFactory(Charset.forName("UTF-8")))); connector.setHandler(new TimeClientHander()); ConnectFuture connectFuture = connector.connect(new InetSocketAddress("192.168.1.124", Constant.PORT_NUMBER)); // 等待建立连接 System.out.println("等待建立连接"); connectFuture.awaitUninterruptibly(); System.out.println("连接成功"); IoSession session = connectFuture.getSession(); PButil.Builder pbutils = PButil.newBuilder(); pbutils.setCode(1); PButil info = pbutils.build(); byte[] result = info.toByteArray(); Scanner sc = new Scanner(System.in); boolean quit = false; while (!quit) { String str = sc.next(); if (str.equalsIgnoreCase("quit")) { quit = true; } session.write(result); } // 关闭 if (session != null) { if (session.isConnected()) { session.getCloseFuture().awaitUninterruptibly(); } connector.dispose(true); } } }其中自定义的界面工厂和服务端相同我就不在重复上传了
PButil.Builder pbutils = PButil.newBuilder(); pbutils.setCode(1); PButil info = pbutils.build(); byte[] result = info.toByteArray();这里使用了protobuf用来传送数据,protobuf的使用在我博客中有
protobuf的简单使用 protobuf文件的编写