前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多人聊天室

多人聊天室

作者头像
汤高
发布2018-01-11 16:52:33
2.9K1
发布2018-01-11 16:52:33
举报
文章被收录于专栏:积累沉淀积累沉淀

最近学完网络线程协议 ,因此写了一个用java编写的聊天室 话不多说 效果如图

这里写图片描述
这里写图片描述

首先 创建服务器端

代码语言:javascript
复制
package com.yc.server;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Type;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yc.bean.JsonModel;
import com.yc.bean.User;
import com.yc.bean.YcConstants;


public class TalkServer {

    private List<ClientSocket> list=new ArrayList<ClientSocket>();

    public static void main(String[] args) throws IOException {
        TalkServer ts=new TalkServer();
        ts.startServer();
    }

    public void startServer() throws IOException{
        ServerSocket ss=new ServerSocket(9998);
        System.out.println("服务器"+ss.getInetAddress()+"启动了,监听了:"+ss.getLocalPort()+"端口");
        while(true){
            Socket s=ss.accept();
            System.out.println("客户端"+ss.getInetAddress()+"联接上了服务器");
            //将这个s存到一个TalkService中,做成一个线程,处理一个与客户端的联接
            ClientSocket cs=new ClientSocket(s);

            Thread t=new Thread(cs);
            t.start();
        }
    }


    //内部类:实现了Runnable接口的内部类,用于封装对一个客户端的操作
    class ClientSocket implements Runnable{         //不写外部类是因为都要操作这个list,写外部类传这个list较为麻烦
        private Socket s;
        private Scanner sc;
        private PrintWriter pw;
        private boolean flag=false;
        private String nickname;
        private String ip;

        public ClientSocket(Socket s){
            this.s=s;
            System.out.println("客户端"+s.getInetAddress()+"连接上了服务器");
            if(s!=null){
                try {
                    sc=new Scanner(s.getInputStream());
                    pw=new PrintWriter(s.getOutputStream()); 
                    flag=true;
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("客户端"+s.getInetAddress()+"掉线了");
                    list.remove(ClientSocket.this);
                    flag=false;
                    sc.close();
                    pw.close();
                    try {
                        s.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            }
        }

        @Override
        public void run() {
            while(flag){
                //读取用户传过来的消息
                if(sc.hasNextLine()){
                    String jsonline=sc.nextLine();
                    parseProtocal(jsonline);
                }
            }
        }

        //解析状态码
        private int parseCode(String jsonline){
            if(jsonline.startsWith("{\"code\":1,")){
                return 1;
            }else if(jsonline.startsWith("{\"code\":3,")){
                return 3;
            }else if(jsonline.startsWith("{\"code\":4,")){
                return 4;
            }
            return 404;
        }

        //发送信息到客户端
        private void sendMsgToAllClient(String jsonline){
            for(ClientSocket cs:list){
                cs.pw.println(jsonline);
                cs.pw.flush();      //必须flush()
            }
        }

        //解析协议
        private void parseProtocal(String jsonline) {
            //判断code的值
            int code=parseCode(jsonline);
            if(code==1){
                //1是普通聊天信息,直接向所有的客户端广播
                sendMsgToAllClient(jsonline);
            }else if(code==3){
                //如果是3,表明有新用户登录
                Gson g=new Gson();
                Type type=new TypeToken<JsonModel<User>>(){}.getType();
                JsonModel<User> jsonModel=g.fromJson(jsonline, type);
                //将这个User存入到list中
                User loginuser=jsonModel.getT();
                List<User> userlist=new ArrayList<User>();
                //将新登录的用户存入到list中
                ClientSocket.this.ip=loginuser.getIp();
                ClientSocket.this.nickname=loginuser.getNickname();
                list.add(ClientSocket.this);
                for(ClientSocket cs:list){
                    User u=new User();
                    u.setIp(cs.ip);
                    u.setNickname(cs.nickname);
                    userlist.add(u);
                }
                sendUserListJson(userlist);
            }else if(code==4){
                //如果是code为4,则要从ClientSocket中删除这个用户
                Gson g=new Gson();
                Type type=new TypeToken<JsonModel<User>>(){}.getType();
                JsonModel<User> jsonModel=g.fromJson(jsonline, type);
                List<User> userlist=new ArrayList<User>();
                list.remove(ClientSocket.this);
                for(ClientSocket cs:list){
                    User u=new User();
                    u.setIp(cs.ip);
                    u.setNickname(cs.nickname);
                    userlist.add(u);
                }
                sendUserListJson(userlist);
            }
        }

        //发送用户列表的json字符串
        public void sendUserListJson(List<User> userlist){
            String jsonline;
            JsonModel<List<User>> jm=new JsonModel<List<User>>();
            jm.setCode(YcConstants.SEND_USERLIST);
            jm.setT(userlist);
            Type t=new TypeToken<JsonModel<User>>(){}.getType();
            Gson g=new Gson();
            jsonline=g.toJson(jm,t);
            for(ClientSocket cs:list ){
                cs.pw.println(jsonline);
                cs.pw.flush();
            }
        }


    }
}

客户端

代码语言:javascript
复制
package com.yc.client;
import java.io.IOException;

public class TalkClient implements Runnable{

    protected Shell shell;
    private Text txtCat;
    private Text txtLocalhost;
    private Text text_2;
    private Text text_3;
    private Table table;
    private Button button;
    private Button button_1;
    private Button button_2;
    private Text text_4;

    private Socket s;
    private Scanner sc;
    private PrintWriter pw;

    private String nickname;

    private boolean flag=false;


    /**
     * Launch the application.
     * @param args
     */
    public static void main(String[] args) {
        try {
            TalkClient window = new TalkClient();
            window.open();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Open the window.
     */
    public void open() {
        Display display = Display.getDefault();
        createContents();
        shell.open();
        shell.layout();
        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
    }

    /**
     * Create contents of the window.
     */
    protected void createContents() {
        shell = new Shell();
        shell.setSize(744, 671);
        shell.setText("SWT Application");
        shell.setLayout(new FillLayout(SWT.HORIZONTAL));

        SashForm sashForm = new SashForm(shell, SWT.NONE);
        sashForm.setOrientation(SWT.VERTICAL);

        Composite composite = new Composite(sashForm, SWT.NONE);
        composite.setLayout(new FillLayout(SWT.HORIZONTAL));

        Group group = new Group(composite, SWT.NONE);
        group.setText("登录");

        Label label = new Label(group, SWT.NONE);
        label.setBounds(21, 26, 36, 17);
        label.setText("昵称:");

        txtCat = new Text(group, SWT.BORDER);
        txtCat.setText("cat");
        txtCat.setBounds(57, 23, 122, 23);

        Label lblip = new Label(group, SWT.NONE);
        lblip.setBounds(233, 26, 59, 17);
        lblip.setText("服务器IP:");

        txtLocalhost = new Text(group, SWT.BORDER);
        txtLocalhost.setText("localhost");
        txtLocalhost.setBounds(292, 23, 122, 23);

        Label label_2 = new Label(group, SWT.NONE);
        label_2.setBounds(459, 26, 36, 17);
        label_2.setText("端口:");

        text_2 = new Text(group, SWT.BORDER);
        text_2.setText("9998");
        text_2.setBounds(496, 23, 104, 23);

        button = new Button(group, SWT.NONE);
        button.setBounds(448, 61, 80, 27);
        button.setText("登录");

        button_1 = new Button(group, SWT.NONE);

        button_1.setBounds(574, 61, 80, 27);
        button_1.setText("断开");

        Composite composite_1 = new Composite(sashForm, SWT.NONE);
        composite_1.setLayout(new FillLayout(SWT.HORIZONTAL));

        Group group_1 = new Group(composite_1, SWT.NONE);
        group_1.setText("聊天记录");
        group_1.setLayout(new FillLayout(SWT.HORIZONTAL));

        SashForm sashForm_1 = new SashForm(group_1, SWT.NONE);

        Composite composite_3 = new Composite(sashForm_1, SWT.NONE);
        composite_3.setLayout(new FillLayout(SWT.HORIZONTAL));

        text_3 = new Text(composite_3, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);

        Composite composite_4 = new Composite(sashForm_1, SWT.NONE);
        composite_4.setLayout(new FillLayout(SWT.HORIZONTAL));

        table = new Table(composite_4, SWT.BORDER | SWT.FULL_SELECTION);
        table.setHeaderVisible(true);
        table.setLinesVisible(true);

        TableColumn tableColumn = new TableColumn(table, SWT.NONE);
        tableColumn.setWidth(121);
        tableColumn.setText("用户昵称");

        TableColumn tblclmnIp = new TableColumn(table, SWT.NONE);
        tblclmnIp.setWidth(134);
        tblclmnIp.setText("IP");
        sashForm_1.setWeights(new int[] {448, 271});

        Composite composite_2 = new Composite(sashForm, SWT.NONE);
        composite_2.setLayout(new FillLayout(SWT.HORIZONTAL));

        Group group_2 = new Group(composite_2, SWT.NONE);
        group_2.setText("发送内容");

        text_4 = new Text(group_2, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CANCEL | SWT.MULTI);
        text_4.setBounds(52, 32, 476, 105);

        Label label_3 = new Label(group_2, SWT.NONE);
        label_3.setBounds(10, 35, 36, 17);
        label_3.setText("内容:");

        button_2 = new Button(group_2, SWT.NONE);

        button_2.setBounds(570, 110, 80, 27);
        button_2.setText("发送");
        sashForm.setWeights(new int[] {97, 378, 152});


        //发送
        button_2.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                String message=text_4.getText().trim().toString();
                if(message==null || message.length()<0||"".equals(message)){
                    MessageDialog.openError(shell, "出错了", "要发送的信息不能为空");
                    return;
                }
                JsonModel<Content> jsonModel=new JsonModel<Content>();
                jsonModel.setCode(YcConstants.SEND_MESSAGE);
                Content c=new Content();
                c.setNickname(nickname);
                c.setIp(s.getLocalAddress().toString());
                c.setMsg(message);

                jsonModel.setT(c);

                //将jsonModel对象转成json字符串,通过gson转
                //通过TypeToken对象,向Gson来说明这个泛型类的构成
                Gson g=new Gson();
                Type type=new TypeToken<JsonModel<Content>>(){}.getType();
                String jsonstring=g.toJson(jsonModel,type);
                pw.println(jsonstring);
                pw.flush();

                text_4.setText("");
            }
        });

        //断开
        button_1.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                if(s==null){
                    return;
                }
                JsonModel<User> jsonModel=new JsonModel<User>();
                jsonModel.setCode(YcConstants.USER_LOGIN_OUT_CODE);
                User user=new User();
                user.setNickname(nickname);
                user.setIp(s.getLocalAddress().toString());
                jsonModel.setT(user);

                //将jsonModel对象转成json字符串,通过gson转
                //通过TypeToken对象,向Gson来说明这个泛型类的构成
                Gson g=new Gson();
                Type type=new TypeToken<JsonModel<User>>(){}.getType();
                String jsonstring=g.toJson(jsonModel,type);
                pw.println(jsonstring);
                pw.flush();

                //退出
                String content=text_3.getText();
                Date d=new Date();
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                content="\n"+nickname+"退出聊天\n\t\t\t\t"+sdf.format(d)+content;
                text_3.setText(content);
                pw.close();
                sc.close();
                try {
                    s.close();
                    s=null;
                    txtCat.setEnabled(true);
                    txtLocalhost.setEnabled(true);
                    text_2.setEnabled(true);
                    button.setEnabled(true);
                    button_1.setEnabled(false);
                    button_2.setEnabled(false);
                    flag=false;
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });

        //登录
        button.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                nickname=txtCat.getText().toString();
                String ip=txtLocalhost.getText().toString();
                String port=text_2.getText().toString();

                int p=Integer.parseInt(port);

                try {
                    s=new Socket(ip, Integer.parseInt(port));
                    sc=new Scanner(s.getInputStream());
                    pw=new PrintWriter(s.getOutputStream());
                    txtCat.setEnabled(false);
                    txtLocalhost.setEnabled(false);
                    text_2.setEnabled(false);
                    button.setEnabled(false);
                    button_1.setEnabled(true);
                    button_2.setEnabled(true);

                    JsonModel<User> jsonModel=new JsonModel<User>();
                    jsonModel.setCode(YcConstants.USER_LOGIN_CODE);
                    User user=new User();
                    user.setNickname(nickname);
                    user.setIp(s.getLocalAddress().toString());
                    jsonModel.setT(user);
                    //将jsonModel对象转成json字符串,通过gson转
                    //通过TypeToken对象,向Gson来说明这个泛型类的构成
                    Gson g=new Gson();
                    Type type=new TypeToken<JsonModel<User>>(){}.getType();
                    String jsonstring=g.toJson(jsonModel,type);
                    pw.println(jsonstring);
                    pw.flush();
                    flag=true;
                    Thread t=new Thread(TalkClient.this);
                    t.start();
                } catch (Exception e1) {
                    e1.printStackTrace();
                    MessageDialog.openError(shell, "出错了", e1.getMessage());
                    txtCat.setEnabled(true);
                    txtLocalhost.setEnabled(true);
                    text_2.setEnabled(true);
                    button.setEnabled(true);
                    button_1.setEnabled(false);
                    button_2.setEnabled(false);
                } 
            }
        });

    }

    @Override
    public void run() {
        //不断的接收服务器的响应
        while( flag ){      //当flag==true
            //接收服务器的回传数据
            if(s!=null&&s.isClosed()==false&&sc!=null&&sc.hasNextLine()){
                String jsonline=sc.nextLine();
                //解析协议
                parseProtocal(jsonline);
            }
        }
    }

    private void parseProtocal(String jsonline) {
        //判断code的值
        int code=parseCode(jsonline);
        if(code==1){
            //如果code==1,则t是content对象,则操作文本显示聊天信息
            Gson g=new Gson();
            Type type=new TypeToken<JsonModel<Content>>(){}.getType();
            JsonModel<Content> jsonModel=g.fromJson(jsonline,type);
            final Content c=jsonModel.getT();
            Display.getDefault().asyncExec(new Runnable(){
                @Override
                public void run() {
                    Date d=new Date();
                    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    String txt=text_3.getText().trim();
                    String msg="\n\n"+c.getNickname()+"对大家说:\n"+c.getMsg()+"\n\t\t\t\t发表时间"+sdf.format(d)+"\n";
                    txt=msg+txt;
                    text_3.setText(txt);
                }
            });
        }else if(code==2){
            //如果code==2,则t是userlist集合对象,则更新table
            Gson g=new Gson();
            Type type=new TypeToken<JsonModel<List<User>>>(){}.getType();
            JsonModel<List<User>> jsonModel=g.fromJson(jsonline,type);
            final List<User> list=jsonModel.getT();
            Display.getDefault().asyncExec(new Runnable(){
                @Override
                public void run() {
                    table.removeAll();
                    for(User u:list){
                        TableItem ti=new TableItem(table,SWT.None);
                        ti.setText(new String[]{u.getNickname(),u.getIp()});
                    }
                }
            });
        }
    }

    private int parseCode(String jsonline) {
        if(jsonline.startsWith("{\"code\":1,")){
            return 1;
        }else if(jsonline.startsWith("{\"code\":2,")){
            return 2;
        }
        return 404;
    }
}

其他辅助类 包括聊天人的个人信息和说的内容

代码语言:javascript
复制
package com.yc.bean;

public class Content {

    private String nickname;
    private String ip;
    private String msg;


    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    @Override
    public String toString() {
        return ip+"\t"+nickname+"\t"+msg;
    }
}
代码语言:javascript
复制
package com.yc.bean;

public class JsonModel<T> {
    private int code;
    private T t;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }

}
代码语言:javascript
复制
package com.yc.bean;

//登录或退出的用户信息
public class User {
    private String nickname;
    private String ip;

    public User() {
        super();
    }

    public User(String nickname, String ip) {
        super();
        this.nickname = nickname;
        this.ip = ip;
    }

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

}
代码语言:javascript
复制
package com.yc.bean;

public class YcConstants {

    //登录的code值为3
    public static final int USER_LOGIN_CODE=3;

    //退出的code值值为4
    public static final int USER_LOGIN_OUT_CODE=4;

    //发送信息的code值为1
    public static final int SEND_MESSAGE=1;

    //发送用户列表的code值为2
    public static final int SEND_USERLIST=2;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016-02-13 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档