Netty+Android搭建一个简易聊天室(实现群聊和私聊)
零,前言
JRBM项目中无论是好友私聊,公开聊天室,还是比赛平台都需要用到长连接,之前没有接触过网络通信等知识,更别说框架了,因此直接上手netty确实有些困难,在前期主要是在b站上看(https://www.bilibili.com/video/av26415011)这个视频,但是一些名词根本没有接触过,看着代码也只能照着敲,根本不知道网络通信是什么原理,什么是http协议,什么是socket,什么是编解码等,于是跟着敲了几节课的代码之后准备从实际项目入手,于是看了( https://www.bilibili.com/video/av16767113)这个聊天室的搭建,至少明白了聊天室的基本结构,然后再入手了《Netty权威指南2》,基本了解了Netty的各个组件的基本用法和基本含义,于是花了两天时间从头搭建了一个能够群聊和私聊的聊天室,仅仅代表本人的粗浅理解,也希望能帮助小白入门,大佬绕行!
一,准备工作
开发环境:android+javaweb,前端(客户端)使用android studio,后端(服务端)使用idea
所需jar包:
主要是三个:
netty的jar包,直接去官网( https://netty.io/)下载最新即可,然后只要压缩包中的netty-all-4.1.29.Final即可
messagepack的jar包,去这个链接( http://repo1.maven.org/maven2/org/msgpack/msgpack/0.6.12/)直接下载msgpack-0.6.12.jar
javassist的jar包,去这个链接( https://github.com/jboss-javassist/javassist/releases)下载最新版的jar包
这三个jar包的作用是,netty负责通信的整体框架,messagepack负责消息的编码和解码,javassist在编解码中需要用到
二,服务端的搭建
创建一个web项目(也可以是javase项目),虽然我写的时候用到了spring,但是这篇文章中就不用spring来管理类了
首先看一下项目的结构,
一共三个包,Coder包放编码和解码器的类,entity包放两个实体类,一个是消息的实体类,所有消息都会被包装成这个ChatMessage类,便于读取,UserChannels用于放当前在线的用户的用户名和其channel地址,这样私聊的时候就可以通过用户名调用目标用户的channel进行消息传送,server包中的类前三个是netty创建连接通道需要用到的比较固定的类,StartServer用于启动服务器。
接下来是服务端搭建的步骤:
1.创建实体类ChatMessage
我们希望传输的数据不仅是简简单单的一个字符串,而是一个有很多信息的实体,因此我们创建一个实体模板,所有的消息都被解码包装成这个类,然后直接对这个类的对象进行读写操作即可
import org.msgpack.annotation.Index;
import org.msgpack.annotation.Message;
//消息实体,协议
@Message
public class ChatMessage {
@Index(0)
private String sendUser;
@Index(1)
private String receiveUser;
@Index(2)
private String message;
@Index(3)
private int messagetype;//1:初始化认证消息,2:聊天消息
public ChatMessage() {
}
public ChatMessage(String sendUser, String receiveUser, String message, int messagetype){
this.sendUser=sendUser;
this.receiveUser=receiveUser;
this.message=message;
this.messagetype=messagetype;
}
public String getSendUser() {
return sendUser;
}
public void setSendUser(String sendUser) {
this.sendUser = sendUser;
}
public String getReceiveUser() {
return receiveUser;
}
public void setReceiveUser(String receiveUser) {
this.receiveUser = receiveUser;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getMessagetype() {
return messagetype;
}
public void setMessagetype(int messagetype) {
this.messagetype = messagetype;
}
@Override
public String toString() {
return "ChatMessage{" +
"sendUser='" + sendUser + '\'' +
", receiveUser='" + receiveUser + '\'' +
", message='" + message + '\'' +
'}';
}
}
这个类包含了发送消息的用户、接受消息的用户、消息的内容、消息的类型,分别生成他们的get和set方法,并且为了方便调试,生成他的tostring方法。
在这里需要注意两点,非常重要!!
1.在这个实体类之前加上@message注解,并且创建他的无参构造函数!!!否则消息是无法被序列化编码再传出去的!!!!!(详情见 https://github.com/msgpack/msgpack-java/issues/226)
2.在成员变量前添加@index()标签,以表明数据的顺序,否则会出现类似这样的错误org.msgpack.MessageTypeException:Expected array, but got raw value
这两步非常非常关键,我也是在这两步卡了很久,网上资
CSDN-Ada助手: 如何证明一个问题是 NP-Hard 或 NP-Complete?
CSDN-Ada助手: 哇, 你的文章质量真不错,值得学习!不过这么高质量的文章, 还值得进一步提升, 以下的改进点你可以参考下: (1)增加条理清晰的目录;(2)提升标题与正文的相关性;(3)使用更多的站内链接。
春天熊: 情况一:WebMvcConfigurer 接口实现类上不加 @EnableWebMvc 注解,则拦截器静态资源排除路径类似于 excludePathPatterns("/", "/index.html", "/favicon.ico", "/css/**", "/js/**", "/font/**"),此时直接访问工程上下路径 http://localhost:8080 可跳转到 resource/static/index.html 情况二:WebMvcConfigurer 接口实现类上加上 @EnableWebMvc 注解,则拦截器静态资源排除路径配置为 excludePathPatterns("/static/**"),此时需要在 SpringMVC 的配置上增加默认 Servlet 处理静态资源和视图控制器配置,否则访问 http://localhost:8080 不会跳转到 index.html
TransPlus: Really bad implementation
橘子花会开�: 牛皮