ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

netty socket简单实现客服聊天功能详细讲解(含安卓用户端,java客户端,java后台程序)

2020-02-22 14:40:36  阅读:235  来源: 互联网

标签:netty java socket 用户端 客服 用户 Id String


依照上一篇: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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有