netty socket简单实现客服聊天功能详细讲解(含安卓用户端,java客户端,java后台程序)
作者:互联网
依照上一篇:https://blog.csdn.net/qq_41966009/article/details/104441452依次按照对应功能写出对应详解。
1.用户端和服务端分别与后台服务器(java后台)通信
1.1用户端(安卓用户端)与后台服务器(java后台)通信
首先创建一个ChatApplication类,主要实现以下功能,方便在MainActivity使用Socket
IO.Options options = new IO.Options();
// private SocketIo
private Socket mSocket;
private Socket mSocket;
{
try {
options.reconnectionAttempts = 2;
options.reconnectionDelay = 1000;//失败重连的时间间隔
options.timeout = 500;//连接超时时间(ms)
// Constants.CHAT_SERVER_URL----->Constants类下面有一个公有静态字符串CHAT_SERVER_URL,这个字符串存储这我们需要连通的IP地址。
mSocket = IO.socket(Constants.CHAT_SERVER_URL,options);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
//返回创建的的Socket
public Socket getSocket() {
return mSocket;
}
在 MainActivity的 onCreate里面注册各种监听
//各种监听事件 以下皆为监听,有写好的监听,也有自己自定义的监听
//ChatApplication类在上面
//如果下面这句话报错,请检查自己的项目是否为AndroidX,若不是,根据对应的包修改。
ChatApplication app = (ChatApplication) getApplication();
mSocket = app.getSocket();
//连接监控注册,若报错,请根据错误依次排查问题
mSocket.on(Socket.EVENT_CONNECT,onConnect);
mSocket.on(Socket.EVENT_ERROR,onEvent_Error);
mSocket.on(Socket.EVENT_CONNECT_ERROR,onEvent_Connect_Error);
//获取客服的Id
mSocket.on("getStaffId"+userId,getStaffId);
//开启连接
mSocket.connect();
如果写到这里,对应监听实现完毕后,就可以着手java后台的开发了。这时候我们要创建一个Maven项目。在pom.xml文件里面添加以下依赖。可能会有一点慢,慢慢等等吧。
<dependencies>
<dependency>
<groupId>com.corundumstudio.socketio</groupId>
<artifactId>netty-socketio</artifactId>
<version>1.7.17</version>
</dependency>
<dependency>
<groupId>io.socket</groupId>
<artifactId>socket.io-client</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
</dependencies>
创建Server类,实现java后台功能
public static void main(String [] args){
//设置地址和端口
Configuration config = new Configuration();
//设置Ip地址,至于为什么是192.168.3.73而不是localhost,请参考我以前的文章
config.setHostname("192.168.3.73");
//设置端口
config.setPort(9000);
SocketIOServer server = new SocketIOServer(config);
//服务监听,监听是否有用户接入
server.addConnectListener(new ConnectListener() {
// 添加客户端连接监听器
public void onConnect(SocketIOClient client) {
String sa = client.getRemoteAddress().toString();
String clientIp = sa.substring(1,sa.indexOf(":"));//获取客户端连接的ip
String clientPort = sa.substring(sa.indexOf(":"));//获取客户端连接的port
System.out.println("First服务端接收客户端的连接信息为:"+sa+"----ip:"+clientIp+" port:"+clientPort);
//不知道如何与客户端对应,好的办法是自己去写对应的函数 如果客户端Client连接成功,发送给Client一个字符串"hello"
client.sendEvent("connected", "hello 我是Server,您已经成功连接");
}
});
//至此服务器端的服务已经开启,我们利用send函数,写一个监听,看服务器端与用户端是否通信成功
server.start();
//默认message事件 send发来的信息 都由此监听处理 在此处理用户发来的个人用户信息
server.addEventListener("message", String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws Exception {
System.out.println("收到用户发来的信息"+s);
}
});
}
至此基本的java后台和用户端已经搭建完毕(纯测试,实际代码应该不能这么写)
我们可以在Android用户端send一条数据给java后台看看是否通信成功了
//Android 用户端的一次点击事件,同样可以用这一句话来测试是否与java后台连接成功
//这里的数字是我们用户的ID,方便后续测试。
mSocket.send("2017030401037:你好");
java后台显示
1.2客服端(安卓用户端)与后台服务器(java后台)通信
同理,根据Android代码,修改后可完成客服端与后台服务器的通信。
2.若用户端接入后台服务器的数量大于客服端接入后台服务器的数量,或者反之。多余的用户或多余的客服则加入对应的“队伍”进行排队(入堆),谁在队伍前面,谁就提前与用户或者客服通信。
首先,我会send一条信息,告诉服务端“我”是谁
Android用户端:
//这里的1代表我是用户端发来的请求,并且带上了我的Id(一般用账号来作为Id)
mSocket.send("1:"+userId);
java客服端:
//这里的0代表我是客服端发来的请求,并且带上了我的Id(一般用账号来作为Id)
socket.send("0:"+staffId);
java后台服务端就会根据收到的数据,分析当前用户是谁,并且根据当前用户客服数量,合理的让用户客服知道他们的客服用户是谁。如果客服的数量小于用户,那么用户会进入他对应的"队伍"中去排队(入堆),如果用户的数量小于客服,那么客服会进入他对应的"队伍"中去排队(入堆)。如果有新的客户或者用户请求加入,那么就会有队伍里面的队首元素(等待最久的人)与之答应。
附上我自己写的java后台处理send函数测试代码:
//默认message事件 send发来的信息 都由此监听处理 在此处理用户发来的个人用户信息
server.addEventListener("message", String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws Exception {
//获取类型,如果getType是1,那么他就是用户;如果是0,就是客服
String getType=s.substring(0,s.indexOf(":"));
//开始获取发来的Id Id1是获取当前“:”前面的字符串,主要用来知道这个长度
String Id1=s.substring(0,s.indexOf(":"));
//获取到Id1的长度后,根据substring函数,来截取获取到的Id
String Id =s.substring(Id1.length()+1,s.length());
System.out.println("获取到type:"+getType);
System.out.println("获取到id:"+Id);
//1是用户 查看Android端代码
//0是客服 查看Java端代码
if(Integer.parseInt(getType)==1){
System.out.println("用户发来的个人信息"+s);
//如果客服队内元素大于0,表示有客服在排队等待用户,这时候就分一个用户给客服
if(staffId.size()>0){
//获取堆内客服的Id
String getStaffId=staffId.get(0).toString();
//发送至客服
System.out.println("即将发送给客服 用户的Id为:"+Id);
//发送给客服,让客服知道它的用户是谁
server.getBroadcastOperations().sendEvent("getUserId"+getStaffId,Id);
//发送给用户,让用户知道他的客服是谁
server.getBroadcastOperations().sendEvent("getStaffId"+Id,getStaffId);
//移除最先进入的客服------FIFO算法
staffId.remove(0);
}else {
System.out.println("用户入堆 Id:"+Id);
userId.add(Id);
}
}else if(Integer.parseInt(getType)==0){
System.out.println("客服发来的个人信息"+s);
if(userId.size()>0){
//获取堆内 用户的Id
String getUserId=userId.get(0).toString();
//发送至用户
System.out.println("即将发送给用户 客服的Id为:"+Id);
server.getBroadcastOperations().sendEvent("getStaffId"+getUserId,Id);
String user1=userId.get(0).toString();
server.getBroadcastOperations().sendEvent("getUserId"+Id,user1);
userId.remove(0);
}else {
System.out.println("客服入堆 Id:"+Id);
staffId.add(Id);
}
}else if(Integer.parseInt(getType)==2){
System.out.println("用户已经成功接入");
}else {
System.out.println("未知身份消息"+s+"拒绝处理");
}
System.out.println("**********************************");
}
});
以上实现了用户知道自己的客服是谁(他们各自获取到了他们的信息(Id)),客服知道自己的用户是谁
3.用户端与客服端通信聊天
我在这里做的最不好,只限实现功能,希望大家告诉我用户端与客服端通信的最好方式。
既然需要客服与用户通信,那么服务端就需要对应监听:
//接收客服发送消息监听 然后发送至用户
server.addEventListener("submitMessageToUser", String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws ClassNotFoundException {
String getAllMessage=s;
String getStaffId=getAllMessage.substring(0,getAllMessage.indexOf(":"));
String getMessage1=s.substring(0,s.indexOf(":"));
String getMessage=s.substring(getMessage1.length()+1,s.length());
System.out.println("收到客服发来的消息"+s+" 收到客服的Id:"+getStaffId+" 收到要发送给用户的信息:"+getMessage);
server.getBroadcastOperations().sendEvent("borcast:"+getStaffId,getMessage);
}
});
//接收用户发送消息监听 然后发送给客服
server.addEventListener("submitMessageToStaff", String.class, new DataListener<String>() {
@Override
public void onData(SocketIOClient socketIOClient, String s, AckRequest ackRequest) throws ClassNotFoundException {
String getAllMessage=s;
String getUserId=s.substring(0,s.indexOf(":"));
String getMessage1=s.substring(0,s.indexOf(":"));
String getMessage=getAllMessage.substring(getMessage1.length()+1,s.length());
System.out.println("收到用户发来的消息"+s+" 收到用户的Id:"+getUserId+" 收到要发送给客服的信息:"+getMessage);
server.getBroadcastOperations().sendEvent("borcast:"+getUserId,getMessage);
}
});
因为上一小节已经讲述了用户端与客服端获取到了他们要通信人的信息,所以我就利用emit函数,发送消息
Android用户端:
//我需要把自己的信息和Id发送出去,Id告诉客服我是谁,信息告诉别人我想跟客服说的话
mSocket.emit("submitMessageToStaff", userId+":"+message);
java客服端
//我需要把自己的信息和Id发送出去,Id告诉用户我是谁,信息告诉别人我想跟客服说的话
socket.emit("submitMessageToUser",staffId+":"+s);
再根据上面服务端的监听,就可以实现消息之间的互传了。
4.图文讲解:https://blog.csdn.net/qq_41966009/article/details/104441452
Github全部代码地址,含Android用户端,java客服端,java后台端:
谁都不许动我的砖 发布了30 篇原创文章 · 获赞 2 · 访问量 3518 私信 关注标签:netty,java,socket,用户端,客服,用户,Id,String 来源: https://blog.csdn.net/qq_41966009/article/details/104442283