Socket实现网络聊天室和联系人私聊功能

来源:互联网 发布:核弹 知乎 编辑:程序博客网 时间:2024/05/18 00:24

使用socket技术实现网络聊天室和私聊功能

话不多说先上图:

  1. 聊天室群聊页面

聊天室群聊页面

  1. 在线用户的联系人列表
    在线用户的联系人列表

  2. socket连接页面
    socket配置页面

  3. 私聊页面
    与在线联系人私聊页面

项目介绍

  1. 与服务端实现socket连接:每个客户端连接到服务器的时候,服务器会将每个连接的socket保存在list集合中。
  2. 群聊功能:当有一个用户发送群聊消息给服务器的时候,服务器会将所有信息转发给list列表中的所有已连接的客户端。
  3. 私聊功能:用户发送私聊信息给服务器后,服务器会向一个目标ip发送消息。
  4. 显示在线联系人列表:当有新用户登录成功的时候,服务器会将在线联系人的信息用json字符串的形式发送给客户端,客户端通过解析json字符串来获取在线联系人的信息。

自定义一个强大的类SocketEvent:客户端与服务器通信全部都是通过这个类来保存数据的,然后使用fastjson工具来把类对象转换为json字符串来传输。

public class SocketEvent {    private int type =0;    private String msg ="";    private String keyIP =""; // 关键IP    private String temporaryIP =""; // 临时IP    public SocketEvent() {    }    public int getType() {        return type;    }    public void setType(int type) {        this.type = type;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public String getKeyIP() {        return keyIP;    }    public void setKeyIP(String keyIP) {        this.keyIP = keyIP;    }    public String getTemporaryIP() {        return temporaryIP;    }    public void setTemporaryIP(String temporaryIP) {        this.temporaryIP = temporaryIP;    }}

type: 标志当前发送的信息是什么类型的信息。服务端和客户端解 析数据就是通过这个它来判断属于哪种类型的消息

public static final int CHAT_PRIVATE  = 111; // 私聊的指令    public static final int CHAT_GROUP  = 222; // 群聊的指令    public static final int SOCKET_SUCCESS  = 333; // socket连接成功的指令    public static final int SOCKET_FAIL  = 444; // socket连接失败的指令    public static final int CONNECT_SUCCESS  = 666; // socket连接成功的指令    public static final int CONNECT_FAIL  = 777; // socket连接失败的指令    public static final int LOGIN_ARG = 888; // socket接收到标志新用户登录的指令    public static final int CANCEL_ARG  = 999; // socket接收到标志用户注销的指令    public static final int NEW_CLIENT  = 3332; // 新用户登录的指令    public static final int ALL_CLIENT  = 3432; // 新用户登录后接收到所有在线用户的指令    public static final int SEND_PRIVATE  = 5666; // 发送私聊消息的指令    public static final int SEND_IPlIST  = 6666; // 发送已登录的用户IP集合的指令

keyIP:客户端消息发起者的ip地址

temperoryIP:临时的IP地址,如果是type是私聊类型的那么这个ip代表的就是目标联系人的ip地址

服务端代码 (ServerSocket)

1. 接收客户端的连接

Socket Socketclient = server.accept();

2.开启线程实时接收来自客户端的信息

// 实时获取客户端发送的数据        @Override        public void run() {            try {                while (true) {                    if ((acceptLine = in.readLine()) != null) {                        System.out.println("<接收到的消息是>" + acceptLine);                        SocketEvent event = JSON.parseObject(acceptLine, SocketEvent.class);                        switch (event.getType()) {                        case UtilFactory.CHAT_GROUP:                            sendMsgAvoid(event.getKeyIP(), acceptLine);                            break;                        case UtilFactory.SEND_PRIVATE:                            event.setType(UtilFactory.CHAT_PRIVATE);                            sendMsgTarget(event.getTemporaryIP(), JSON.toJSONString(event));                            break;                        }                    }                }            } catch (Exception e) {                e.printStackTrace();            }        }

3. 向指定ip发送消息的方法和除了自己ip向其他所有ip发送消息的方法

// 向指定的ip地址发送消息        private void sendMsgTarget(String targetIP, String msg) {            int num = mList.size();            for (int index = 0; index < num; index++) {                Socket mSocket = mList.get(index);                String ip = mSocket.getInetAddress().getHostAddress();                if (ip.equals(targetIP)) {                    PrintWriter pout = null;                    try {                        pout = new PrintWriter(                                new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);                        pout.println(msg);                        // 退出方法                        return;                    } catch (IOException e) {                        e.printStackTrace();                    }                }            }        }        // 向除了这个ip以外的所有ip发送        private void sendMsgAvoid(String avoidIP, String msString) {            int num = mList.size();            for (int index = 0; index < num; index++) {                Socket mSocket = mList.get(index);                String ip = mSocket.getInetAddress().getHostAddress();                if (!ip.equals(avoidIP)) {                    PrintWriter pout = null;                    try {                        pout = new PrintWriter(                                new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream(), "UTF-8")), true);                        pout.println(msString);                    } catch (IOException e) {                        e.printStackTrace();                    }                }            }        }

客户端在mainActivity中接受来自服务端的所有信息,根据type来进行再次分装,使用Eventbus将信息发送给各个fragment来进行展示

@Subscribe(threadMode = ThreadMode.MAIN)    public void privateChat(SocketEvent event) {        switch (event.getType()) {            case MyApplication.CHAT_PRIVATE:                // 将消息post给私聊聊天室                ChatMessageBean bean = new ChatMessageBean();                bean.setMsg(event.getMsg());                bean.setName(event.getKeyIP());                bean.setType(ChatMessageBean.OTHERS_ARG);                EventBus.getDefault().post(bean);                break;            case MyApplication.SEND_PRIVATE:                sendMsg(JSON.toJSONString(event));                break;        }    }
0 0