netty PBProtocol demo

 PBMessage 结构体

package com.road.message;

import io.netty.buffer.ByteBuf;

import java.nio.ByteBuffer;

import org.apache.mina.core.buffer.IoBuffer;

import com.google.protobuf.Message;

public class PBMessage {
	private static final long serialVersionUID = 1L;
	public static final short HDR_SIZE = 10;
	public static final short HEADER = 0x71ab;

	private short header = HEADER;
	private short len;
	private short code;
	private int playerId;

	private int byteLength;
	private byte[] bytes;

	private Message message; // Proto

	private byte opCode = 0x2;
	private Object myMsg;

	public PBMessage() {

	}

	public PBMessage(Object myMsg) {
		this.myMsg = myMsg;
	}

	public PBMessage(short code, byte[] bytes) {
		this(code, -1);
		this.bytes = bytes;
	}

	public PBMessage(short code) {
		this(code, -1);
	}

	public PBMessage(short code, int playerId) {
		this.code = code;
		this.playerId = playerId;
	}

	public PBMessage(short code, Object myMsg) {
		this.code = code;
		this.myMsg = myMsg;
	}

	public PBMessage(short code, int playerId, Object myMsg) {
		this.code = code;
		this.playerId = playerId;
		this.myMsg = myMsg;
	}

	public short getHeader() {
		return header;
	}

	public short getLen() {
		return len;
	}

	public void setLen(short len) {
		this.len = len;
	}

	public short getCode() {
		return code;
	}

	public void setCode(short code) {
		this.code = code;
	}

	public int getPlayerId() {
		return playerId;
	}

	public void setPlayerId(int playerId) {
		this.playerId = playerId;
	}

	public byte[] getBytes() {
		return bytes;
	}

	public void setBytes(byte[] bytes) {
		this.bytes = bytes;
	}

	public Message getMessage() {
		return message;
	}

	public void setMessage(Message message) {
		this.message = message;
	}

	public void readHeader(ByteBuffer in) {
		in.getShort();
		len = in.getShort();
		code = in.getShort();
		playerId = in.getInt();
	}

	public void readHeader(IoBuffer in) {
		in.getShort();
		len = in.getShort();
		code = in.getShort();
		playerId = in.getInt();
	}

	public void readHeaderNetty(ByteBuf in) {
		in.readShort();
		len = in.readShort();
		code = in.readShort();
		playerId = in.readInt();
	}

	public void readHeader1(IoBuffer in) {
		in.getShort();
		len = in.getShort();
		code = in.getShort();
		playerId = in.getInt();

		bytes = new byte[len - 10];
		in.get(bytes, 0, bytes.length);
	}

	public void read(ByteBuf in) {
		in.readShort();
		len = in.readShort();
		code = in.readShort();
		playerId = in.readInt();

		bytes = new byte[in.capacity() - 10];
		in.readBytes(bytes);
	}

	public void writeHeader(int len, ByteBuffer out) {
		out.putShort(HEADER);
		out.putShort((short) len);
		out.putShort(code);
		out.putInt(playerId);
	}

	public void writeHeader(int len, IoBuffer out) {
		out.putShort(HEADER);
		out.putShort((short) len);
		out.putShort(code);
		out.putInt(playerId);
	}

	public void writeHeader(int len, ByteBuf out) {
		out.writeShort(HEADER);
		out.writeShort((short) len);
		out.writeShort(code);
		out.writeInt(playerId);
		if (message != null) {
			out.writeBytes(message.toByteArray());
		}

		else if (bytes != null) {
			if (byteLength != 0) {
				out.writeBytes(bytes, 0, byteLength);
			} else {
				out.writeBytes(bytes);
			}
		}
	}

	public void writeHeaderByte(int len, ByteBuf out) {
		out.writeShort(HEADER);
		out.writeShort((short) len);
		out.writeShort(code);
		out.writeInt(playerId);
		if (bytes != null) {
			out.writeBytes(bytes);
		}
	}

	public void writeHeartbeat(int len, ByteBuf out) {
		out.writeShort(HEADER);
		out.writeShort((short) len);
		out.writeShort(code);
		out.writeInt(playerId);
	}

	public byte[] toByteArray() {
		return bytes;
	}

	public short calcChecksum(byte[] data) {
		int val = 0x77;
		int i = 6;
		int size = data.length;
		while (i < size) {
			val += (data[i++] & 0xFF);
		}
		return (short) (val & 0x7F7F);
	}

	public String headerToStr() {
		StringBuilder sb = new StringBuilder();
		sb.append("playerId : ").append(playerId);
		sb.append(", code : ").append(Integer.toHexString(code));
		sb.append(", len : ").append(len);
		return sb.toString();
	}

	public String detailToStr() {
		if (bytes == null) {
			return null;
		}
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(b + ", ");
		}
		return headerToStr() + ", content : [" + sb.toString() + "]";
	}

	public byte getOpCode() {
		return opCode;
	}

	public void setOpCode(byte opCode) {
		this.opCode = opCode;
	}

	public Object getMyMsg() {
		return myMsg;
	}

	public void setMyMsg(Object myMsg) {
		this.myMsg = myMsg;
	}

	public int getByteLength() {
		return byteLength;
	}

	public void setByteLength(int byteLength) {
		this.byteLength = byteLength;
	}

	@Override
	public PBMessage clone() {
		PBMessage clone = null;
		try {
			clone = (PBMessage) super.clone();
			clone.setMessage(message);
			return clone;
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
			return null;
		}
	}
}

server

package com.road.nettysocket;

import com.road.code.ProtoBufDecoderNew;
import com.road.code.ProtoBufEncoderNew;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class NettyServer {

    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(4);  
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(4); 
    
	public void bind(int port)
	{
	   ServerBootstrap b = new ServerBootstrap();
	   b.group(bossGroup,workerGroup)
	    .channel(NioServerSocketChannel.class)
	    .childHandler(new ChildChannelHandler());
	   
	   try {
		   ChannelFuture f = b.bind("127.0.0.1",port).sync();
		   f.channel().closeFuture().sync();
	   } catch (InterruptedException e) {
		    e.printStackTrace();
	   }finally
	   {
		   bossGroup.shutdownGracefully();
		   workerGroup.shutdownGracefully();
	   }
	}
	
	private class ChildChannelHandler extends ChannelInitializer<SocketChannel>
	{
		@Override
		protected void initChannel(SocketChannel channel) throws Exception {
			channel.pipeline().addLast("decoder", new ProtoBufDecoderNew());
			channel.pipeline().addLast("encoder", new ProtoBufEncoderNew());
			channel.pipeline().addLast(new ServerHandler());
		}
	}
	
	public static void main(String[] args)
	{
		new NettyServer().bind(9500);
	}
}


package com.road.nettysocket;

import com.road.message.PBMessage;
import com.road.snake.pb.PlayerDeadMsgProto.PlayerDeadMsg;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ServerHandler extends SimpleChannelInboundHandler<PBMessage>{

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		
	}
	
	@Override
	protected void channelRead0(ChannelHandlerContext ctx, PBMessage msg)
			throws Exception {
		
		PlayerDeadMsg req = PlayerDeadMsg.parseFrom(msg.toByteArray());
		System.out.println("getDeadUserId=="+req.getDeadUserId());
		System.out.println("KillUserId=="+req.getKillUserId());
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("连接断开 : " + ctx.channel().remoteAddress());
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		System.out.println("连接异常 : " + ctx.channel().remoteAddress() + " error : " + cause);
		ctx.close();
	}

}

package com.road.code;

import java.util.List;
import com.road.message.PBMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class ProtoBufDecoderNew extends ByteToMessageDecoder {

	@Override
	protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
		if (in.readableBytes() < PBMessage.HDR_SIZE) {
			return;
		}

		ByteBuf byteBuf = in.slice();
		short headerFlag = byteBuf.readShort();
		if (PBMessage.HEADER != headerFlag) {
			byteBuf.readShort();
			return;
		}

		int lenght = byteBuf.readShort();
		if (lenght <= 0 || lenght >= Short.MAX_VALUE) {
			System.out.println("Message Length Invalid Length = " + lenght + ", drop this Message.");
			return;
		}

		if (lenght > in.readableBytes()) {
			return;
		}

		PBMessage pkg = new PBMessage();
		pkg.readHeaderNetty(in);
		int bodyLen = lenght - PBMessage.HDR_SIZE;
		if (bodyLen > 0) {
			byte[] bytes = new byte[bodyLen];
			in.readBytes(bytes, 0, bodyLen);
			pkg.setBytes(bytes);
		}

		out.add(pkg);
	}

}


package com.road.code;

import java.io.IOException;
import java.util.List;
import com.google.protobuf.Message;
import com.road.message.PBMessage;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;

public class ProtoBufEncoderNew extends MessageToMessageEncoder<PBMessage> {

	@Override
	protected void encode(ChannelHandlerContext ctx, PBMessage msg, List<Object> out) throws Exception {
		Object object = msg.getMyMsg();
		if (object != null && msg.getMyMsg() instanceof PBMessageBuffer) {
			PBMessageBuffer messageBuffer = (PBMessageBuffer) msg.getMyMsg();
			for (PBMessage message : messageBuffer) {
				encodeMessage(ctx, message, out);
			}
		} else {
			encodeMessage(ctx, msg, out);
		}
	}

	private void encodeMessage(ChannelHandlerContext ctx, PBMessage message, List<Object> out) throws IOException {
		Message pbMessage = message.getMessage();
		int size = PBMessage.HDR_SIZE;
		if (pbMessage != null) {
			size = PBMessage.HDR_SIZE + pbMessage.getSerializedSize();
		} else {
			byte[] bytes = message.getBytes();
			if (bytes != null) {
				size = PBMessage.HDR_SIZE + bytes.length;
			}
		}
		if (size > Short.MAX_VALUE) {
			return;
		}

		ByteBuf buffer = ctx.alloc().buffer(size);
		message.writeHeader(size, buffer);
		out.add(buffer);
	}
}


package com.road.code;

import java.util.ArrayList;

import com.road.message.PBMessage;

public class PBMessageBuffer extends ArrayList<PBMessage> {
	private static final long serialVersionUID = 1L;
}


package com.road.code;

import com.google.protobuf.AbstractMessage.Builder;
import com.google.protobuf.Message;
import com.road.message.PBMessage;

/**
 * 鏉堝懎濮猾锟�
 */
public class MessageUtil {

	/**
	 * 濞戝牊浼呴崚娑樼紦
	 * 
	 * @param code
	 * @param messageBuilder
	 * @return
	 */
	public static PBMessage buildMessage(short code, Builder<?> messageBuilder) {
		return buildMessage(code, messageBuilder.build());
	}

	/**
	 * 濞戝牊浼呴崚娑樼紦
	 * 
	 * @param code
	 * @param messageBuilder
	 * @return
	 */
	public static PBMessage buildMessage(short code, Message message) {
		PBMessage response = new PBMessage(code, -1);
		response.setMessage(message);
		return response;
	}

	public static PBMessage buildMessageByte(short code, byte[] data) {
		PBMessage response = new PBMessage(code, -1);
		response.setBytes(data);
		return response;
	}

	public static PBMessage buildMessageByte(short code, int userId, byte[] data) {
		PBMessage response = new PBMessage(code, userId);
		response.setBytes(data);
		return response;
	}

	public static PBMessage buildMessageByte(short code, int userId, int byteLength, byte[] data) {
		PBMessage response = new PBMessage(code, userId);
		response.setByteLength(byteLength);
		response.setBytes(data);
		return response;
	}

	/**
	 * 濞戝牊浼呴崚娑樼紦
	 * 
	 * @param code
	 * @param client
	 * @param messageBuilder
	 * @return
	 */
	public static PBMessage buildMessage(short code, int client, Builder<?> messageBuilder) {
		PBMessage response = new PBMessage(code, client);
		response.setMessage(messageBuilder.build());
		return response;
	}

	/**
	 * 濞戝牊浼呴崚娑樼紦
	 * 
	 * @param code
	 * @param client
	 * @return
	 */
	public static PBMessage buildMessage(short code, int client) {
		PBMessage message = new PBMessage(code, client);
		return message;
	}

	/**
	 * 濞戝牊浼呴崚娑樼紦
	 * 
	 * @param code
	 * @param messageBuilder
	 * @return
	 */
	public static PBMessage buildMessage(short code, Object object) {
		PBMessage response = new PBMessage(code, object);
		return response;
	}
}

package com.road.nettysocket;

import com.road.code.MessageUtil;
import com.road.code.ProtoBufDecoderNew;
import com.road.code.ProtoBufEncoderNew;
import com.road.message.PBMessage;
import com.road.snake.pb.PlayerDeadMsgProto.PlayerDeadMsg;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class NettyClient {

	public static Channel channel;
	 
	public void connect(int port,String host)
	{
		EventLoopGroup group = new NioEventLoopGroup();
		Bootstrap b = new Bootstrap();
		b.group(group)
		 .channel(NioSocketChannel.class)
		 .option(ChannelOption.TCP_NODELAY, true)
		 .handler(new ChildChannelHandler());
		
		b.option(ChannelOption.SO_KEEPALIVE, true);  
		
		try {
			ChannelFuture future =b.connect(host, port).sync();
			channel = future.channel();
			//channel.closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally
		{
			//group.shutdownGracefully();
		}
	}
	
	private class ChildChannelHandler extends ChannelInitializer<SocketChannel>
	{
		@Override
		protected void initChannel(SocketChannel channel) throws Exception {
			channel.pipeline().addLast("decoder", new ProtoBufDecoderNew());
			channel.pipeline().addLast("encoder", new ProtoBufEncoderNew());
			channel.pipeline().addLast(new ClientHandler());
		}
	}
	
	 public static void sendMsg(String msg) throws Exception {  
	        if(channel!=null){  
	            channel.writeAndFlush(msg).sync();  
	        }else{  
	            System.out.println("消息发送失败,连接尚未建立!");  
	        }  
	    }
	
	public static void main(String[] args)
	{
		new NettyClient().connect(9500, "127.0.0.1");
		
		PlayerDeadMsg.Builder msg = PlayerDeadMsg.newBuilder();
		msg.setDeadUserId(100);
		msg.setKillUserId(200);
		
		PBMessage message = MessageUtil.buildMessage((short)125, msg);
		
		  for (int i = 0; i < 100000; i++) {  
	        	try {
	        		sendPacket(message);
				} catch (Exception e) {
					e.printStackTrace();
				}  
	       }  
	}
	
	public static void sendPacket(PBMessage message) {
		if (!channel.isActive()) {
			return;
		}

		message.setPlayerId(522);
		int size = message.getMessage().getSerializedSize() + 10;
		ByteBuf respBuffer = Unpooled.buffer(size);
		message.writeHeader(size, respBuffer);
		try {
			channel.writeAndFlush(message).sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


package com.road.nettysocket;

import com.road.message.PBMessage;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ClientHandler extends SimpleChannelInboundHandler<PBMessage>{

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, PBMessage msg)
			throws Exception {
		
		
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		System.out.println("连接断开 : " + ctx.channel().remoteAddress());
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		System.out.println("连接异常 : " + ctx.channel().remoteAddress() + " error : " + cause);
	}
  
}


重要的地方:

channel.pipeline().addLast("decoder", new ProtoBufDecoderNew());
        channel.pipeline().addLast("encoder", new ProtoBufEncoderNew());

猜你喜欢

转载自blog.csdn.net/shizhan1881/article/details/71512317