Android 长连接Netty
Posted 吹着空调哼着歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 长连接Netty相关的知识,希望对你有一定的参考价值。
netty
准备工作
依赖:
implementation 'io.netty:netty-all:4.1.36.Final'
compileOnly "org.projectlombok:lombok:1.16.18"
implementation 'org.glassfish:javax.annotation:10.0-b28'
导入jar包:
libs–>fastjson-1.2.49.jar
*下方有demo下载获取
netty
ChatProto自定义消息格式与消息文体
/**
* Created by ICE on 2021年1月11日.
*/
public class ChatProto
//header
public static final int PING_PROTO = 1 << 8 | 220; //ping消息
public static final int PONG_PROTO = 2 << 8 | 220; //pong消息
public static final int SYS_PROTO = 3 << 8 | 220; //系统消息
public static final int ERROR_PROTO = 4 << 8 | 220; //错误消息
public static final int AUTH_PROTO = 5 << 8 | 220; //认证消息
public static final int MSG_PROTO = 6 << 8 | 220; //普通消息
public int getHead()
return head;
public void setHead(int head)
this.head = head;
public String getBody()
return timestamp;
public void setBody(String timestamp)
this.timestamp = timestamp;
public Map<String, Object> getExtend()
return extend;
public void setExtend(Map<String, Object> extend)
this.extend = extend;
private int head;
private String timestamp;
private Map<String, Object> extend;
public ChatProto(int head, String timestamp)
this.head = head;
this.timestamp = timestamp;
this.extend = new HashMap<>();
public static MessageProtocol buildPingProto()
// Log.i("TAG","ping");
return buildProto(PING_PROTO);
public static MessageProtocol buildMsgProto(@NonNull Integer code)
ChatProto chatProto = new ChatProto(MSG_PROTO, null);
Log.i("TAG", JSONObject.toJSONString(chatProto)+"");
return buildProto(MSG_PROTO, code, null);
public static MessageProtocol buildPongProto()
return buildProto(PONG_PROTO);
public static MessageProtocol buildSysProto(int code, @NonNull String msg)
return buildProto(SYS_PROTO, code, msg);
public static MessageProtocol buildErrProto(int code, @NonNull String msg)
return buildProto(ERROR_PROTO, code, msg);
public static MessageProtocol buildMsgProto(@NonNull Integer code, @NonNull Long apkId)
ChatProto chatProto = new ChatProto(MSG_PROTO, null);
chatProto.extend.put("code", code);
chatProto.extend.put("apkId", apkId);
chatProto.extend.put("time", System.currentTimeMillis());
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
public static MessageProtocol buildMsgProto(@NonNull Integer code, @Nullable Integer count)
ChatProto chatProto = new ChatProto(MSG_PROTO, null);
chatProto.extend.put("code", code);
if (null != count)
chatProto.extend.put("count", count);
chatProto.extend.put("time", System.currentTimeMillis());
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
public static MessageProtocol buildAuthProto(@Nullable @NonNull String token, @Nullable @NonNull Long giftId, Object o)
ChatProto chatProto = new ChatProto(AUTH_PROTO, null);
// if (null != token)
// chatProto.extend.put("nickName", token);
//
// if (null != giftId)
// chatProto.extend.put("giftId", giftId);
//
// chatProto.extend.put("time", System.currentTimeMillis());
chatProto.extend.put("发送数据","发送数据");
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
public static MessageProtocol buildMsgProto(@Nullable Long giftId, @NonNull String nickName, @Nullable @NonNull Integer level, String msg)
ChatProto chatProto = new ChatProto(MSG_PROTO, null);
if (null != level)
chatProto.extend.put("level", level);
if (!nickName.isEmpty())
chatProto.extend.put("nickName", nickName);
if (null != giftId)
chatProto.extend.put("giftId", giftId);
chatProto.extend.put("time", System.currentTimeMillis());
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
public static MessageProtocol buildMsgProto(int code, @NonNull String nickName, @Nullable Integer level, @Nullable Long giftId, @Nullable Integer count, String msg)
ChatProto chatProto = new ChatProto(MSG_PROTO, msg);
chatProto.extend.put("code", code);
if (!nickName.isEmpty())
chatProto.extend.put("nickName", nickName);
if (null != level)
chatProto.extend.put("level", level);
if (null != giftId)
chatProto.extend.put("giftId", giftId);
if (null != count)
chatProto.extend.put("count", count);
chatProto.extend.put("time", System.currentTimeMillis());
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
private static MessageProtocol buildProto(int head)
ChatProto chatProto = new ChatProto(head, null);
Log.i("TAG","发送数据-------JSONObject "+ JSONObject.toJSONString(chatProto));
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
@NonNull
private static MessageProtocol buildProto(int head, int code, @NonNull String msg)
ChatProto chatProto = new ChatProto(head, null);
chatProto.extend.put("code", code);
chatProto.extend.put("msg", msg);
String bytes = JSONObject.toJSONString(chatProto);
MessageProtocol messageProtocol = new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
Log.i("TAG","发送数据------- "+messageProtocol);
return new MessageProtocol(JSONObject.toJSONString(chatProto).getBytes());
public static void main(String[] args)
ChatProto chatProto = new ChatProto(AUTH_PROTO, "哈喽,world!!!");
chatProto.extend.put("userId", 2L);
chatProto.extend.put("userName", "n_7777777");
chatProto.extend.put("level", 1);
chatProto.extend.put("time", System.currentTimeMillis());
String message = JSONObject.toJSONString(chatProto);
System.out.println(">>>>>" + message);
System.out.println("======" + Unpooled.copiedBuffer(message.getBytes()).toString(CharsetUtil.UTF_8));
ChatProto chatProto1 = new ChatProto(PING_PROTO, null);
String message1 = JSONObject.toJSONString(chatProto1);
System.out.println(">>>>>" + message1);
try
String enStr = URLEncoder.encode(message, "UTF-8");
System.out.println(">>>>>" + enStr);
String enStr1 = URLEncoder.encode(message1, "UTF-8");
System.out.println(">>>>>" + enStr1);
catch (Exception e)
e.printStackTrace();
MessageEncoder MessageDecoder 消息加密处理类
/**
* Created by ICE on 2021年1月11日.
*/
public class MessageDecoder extends ByteToMessageDecoder
/**
* <pre>
* 协议开始的标准head_data,int类型,占据4个字节.
* 表示数据的长度contentLength,int类型,占据4个字节.
* </pre>
*/
public static final int BASE_LENGTH = 4 + 4;
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, @NonNull ByteBuf byteBuf, @NonNull List<Object> list) throws Exception
//可读长度大于基本长度
if (byteBuf.readableBytes() > BASE_LENGTH)
//防止socket字节流攻击
//防止客户端传来的数据过大
if (byteBuf.readableBytes() > 2048)
byteBuf.skipBytes(byteBuf.readableBytes());
//记录包头开始的index
int beginReader;
while (true)
//获取包头开始的index
beginReader = byteBuf.readerIndex();
//标记包头开始的index
byteBuf.markReaderIndex();
//读到了协议的开始标志,结束while循环
if (byteBuf.readInt() == ConstantValue.HEAD_DATA)
break;
//未读到包头,略过一个字符,继续读取包头的开始标记信息
byteBuf.resetReaderIndex();
byteBuf.readByte();
//当略过一个字符后,数据包长度不符合,等待后续数据到达
if (byteBuf.readableBytes() < BASE_LENGTH)
return;
//消息的长度
int length = byteBuf.readInt();
//判断数据包是否完整
if (byteBuf.readableBytes() < length)
//还原读指针
byteBuf.readerIndex(beginReader);
return;
//读取消息内容
byte[] data = new byte[length];
byteBuf.readBytes(data);
MessageProtocol protocol = new MessageProtocol(data);
list.add(protocol);
/**
* Created by ICE on 2021年1月11日.
*/
public class MessageEncoder extends MessageToByteEncoder<MessageProtocol>
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, @NonNull MessageProtocol messageProtocol, @NonNull ByteBuf byteBuf) throws Exception
//写入消息
//1.写入消息的开头信息标志(int)
byteBuf.writeInt(messageProtocol.getHeadData());
//2.写入消息的长度(int)
byteBuf.writeInt(messageProtocol.getContentLength());
//3.写入消息的内容(byte[])
byteBuf.writeBytes(messageProtocol.getContent());
SocketUtils文本消息转换类
/**
* Created by ICE on 2021年1月11日.
*/
public class SocketUtils
@RequiresApi(api = Build.VERSION_CODES.N)
public static String transfer(@NonNull ByteBuf buf)
if (Objects.isNull(buf))
return "";
String str;
if (buf.hasArray())
str = new String(buf.array(), buf.arrayOffset() + buf.readerIndex(), buf.readableBytes());
else
byte[] bytes = new byte[buf.readableBytes()];
buf.getBytes(buf.readerIndex(), bytes);
str = new String(bytes, 0, buf.readableBytes());
return str;
SocketClient启动类
/**
* Created by ICE on 2019-06-10.
*/
@Slf4j
public class SocketClient implements Start
private Channel channel;
private final Bootstrap bs = new Bootstrap();
private final EventLoopGroup group = new NioEventLoopGroup();
private final SocketClientHandler handler = new SocketClientHandler(this);
private String host;
private int port;
private MessageListener listener;
private String token;
public MessageListener getListener()
return listener;
public String getToken()
return token;
public void addListener(MessageListener listener)
this.listener = listener;
public SocketClient()
bs.group(group)
.channel(NiosocketChannel.class)
// 以上是关于Android 长连接Netty的主要内容,如果未能解决你的问题,请参考以下文章