zoukankan      html  css  js  c++  java
  • java 基于TCP/IP协议的局域网聊天小程序

    有6个模块

    1.用户登录

    2.两两私聊

    3.群发消息

    4.退出登录

    5.关闭服务器

    6.文件传输

    一、用户登录
    客户端:
    1、发送登录信息:LOGIN|Username
    处理USERLISTS命令:所有在线用户的用户名
    2、处理新上线用户信息:ADD|username

    服务器端:
    1、得到所有在线用户信息名称,发回给客户端:USERLISTS|user1_user2_user3
    2、将当前登录的Socket信息放入Arraylist中
    3、将当前登录用户的信息(用户名),发送给已经在线的其他用户:ADD|userName

    二、两两私聊
    客户端:
    1、选择用户
    2、组织一个交互协议,发送到服务器:MSG|SenderName|RecName|MSGInfo
    3、接收服务器转发回的消息
    服务器端:
    1、通过RecName用户名查找,找到目标SocketChat
    2、向目标对象发送消息:MSG|SenderName|MSGInfo

    三、群聊
    MSG|Sendername|ALL|MSGInfo

    四、用户退出连接
    客户端:
    1、向服务器发送下线消息:OFFLINE|username
    2、关闭ClientChat,清空在线用户列表

    3、处理下线用户信息:DEL|username
    删除用户列表中的username

    服务器端:
    1、处理OFFLINE
    2、向所有的其他在线用户发送用户下线消息:DEL|username
    3、清除ArrayList中的当前用户信息(socketChat)

    五、服务器关闭
      客户端:
    1、处理CLOSE命令:界面显示服务器关闭

    2、关闭ClientChat
    3、清空在线用户列表


    服务器端:
    1、向所有在线用户发送关闭服务器的信息:CLOSE

    2、遍历Arraylist将其中的每一个SocketChat关闭
    3、ArrayList要清空
    4、关闭SokcetListener
    5、关闭ServerSocket

     六、文件传输

    客户端:
    准备工作:1,2,3
    //1从本地选中一个文件,获取其文件相关信息(文件名,文件长度)

    //2创建文件传输的服务器,与服务器接通

    //3组织文件传输交互协议进行传输

    //FILETRANS|sendername|recname|文件名|文件长度|IP|Port

    处理服务器转发的内容,处理该内容确认是接收还是拒收,如果接收,建立连接通道接收文件(即开启fileRec线程)
    如果拒收,组织拒收交互协议(FILECANCEL|拒收者|被拒收者)发送给服务器

    服务器端:

    接收发来的消息串,提取发送者+接收者+发送内容+传送文件的IP和Port 进行转发

    服务器收到交互协议:FILECANCEL|拒收者|被拒收者 重新组织交互协议FILECANCELReturn|拒收者 要通知被拒收者,被拒收的消息

    群发的流程图比较简单就没有画

    六、文件传输

     


    以下代码只需修改以下IP地址和端口号即可运行,后期准备对发送消息的内容进行加密用Base64加密方法加密

    客户端代码:
    package rjxy.lkl.Client;
    
    import java.io.*;
    import java.net.*;
    
    public class ClientChat extends Thread {
    
        Socket socket;
        BufferedReader br = null;
        PrintWriter pw = null;
        String UserName;
    
        public ClientChat(Socket socket, String userName) {
            this.socket = socket;
            UserName = userName;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream(),
                        "UTF-8"));
                pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream(), "UTF-8")));
                
            } catch (Exception e) {
                e.printStackTrace();
            }
            //约定一个登录的交互协议Login|username
            sendMSG("Login|"+UserName);
        }
        public void sendMSG(String str){
            pw.println(str);
            pw.flush();
        }
        //断开socket连接
        public void closeChat(){
            try {
                if(socket!=null) socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        //处理服务器发过来的在线用户List ,交互协议为:USERLISTS|user1_user2_user3
        public void run() {
            try {
                String str = "";
                while((str = br.readLine())!=null){
                    System.out.println("---"+str+"---");
                    String comms[] = str.split("[|]");
                    if(comms[0].equals("USERLISTS")){
                        String users[] = comms[1].split("_");
                        ClientMG.getClientMG().addItems(users);
                    } else if(comms[0].equals("ADD")){
                        ClientMG.getClientMG().addItem(comms[1]);
                    } else if(comms[0].equals("MsgReturn")){
                        //"MsgReturn|"+sender+"|"+msg
                        String sender = comms[1];
                        String msg = comms[2];
                        ClientMG.getClientMG().setLog("【"+sender+"】:");
                        ClientMG.getClientMG().setLog(msg);
                    } else if(comms[0].equals("DEL")){
                        //交互协议为:"DEL|"+UserName
                        String sUser = comms[1];
                        ClientMG.getClientMG().removeItem(sUser);
                        ClientMG.getClientMG().setLog(sUser+"已下线");
                    } else if(comms[0].equals("CLOSE")){
                        ClientMG.getClientMG().setLog("服务器已关闭");
                        //关闭ClientChat
                        ClientMG.getClientMG().getClientChat().closeChat();
                        //清空在线用户列表
                        ClientMG.getClientMG().clearItems();
                    } else if(comms[0].equals("FILETRANS")){
                        //"FILETRANS|"+sender+"|"+sFname+"|"+finfo.length()+"|"+IP+"|"+Port
                        String sender = comms[1];
                        String fileName = comms[2];
                        int filelen = Integer.parseInt(comms[3]);
                        String sIP = comms[4];
                        int port = Integer.parseInt(comms[5]);
                        //调用ClientMG中的接收文件的方法
                        ClientMG.getClientMG().recFile(sender, fileName, filelen, sIP, port);
                        
                    } else if(comms[0].equals("FILECANCEL")){
                        ClientMG.getClientMG().cancelFileTrans();
                    } else if (comms[0].equals("FILECANCELReturn")){
                        //FILECANCELReturn|拒收者A
                        ClientMG.getClientMG().setLog(comms[1]+"取消了传输。。。");
                    }
                    
                }
                
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    if (br != null)
                        br.close();
                    if (pw != null)
                        pw.close();
                    if (socket != null)
                        socket.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
    }
    package rjxy.lkl.Client;
    
    import java.awt.BorderLayout;
    
    public class ClientForm extends JFrame {
    
        private JPanel contentPane;
        public JPanel panel;
        public JLabel lblIp;
        public JTextField txtIP;
        public JLabel label_1;
        public JTextField txtPort;
        public JButton btnLogin;
        public JButton btnExit;
        public JPanel panel_1;
        public JButton btnSend;
    
        Socket socket;    
        BufferedReader br=null;
        PrintWriter pw=null;
        public JScrollPane scrollPane;
        public JTextArea txtLog;
        public JScrollPane scrollPane_1;
        public JTextArea txtSend;
        public JLabel label;
        public JTextField txtUser;
        public JScrollPane scrollPane_2;
        public JList lOnlines;
        
        DefaultListModel<String> items=new DefaultListModel<String>();
        public JButton sendToAll;
        public JButton FileTranbutton;
        public JProgressBar FileprogressBar;
        /**
         * Launch the application.
         */
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        ClientForm frame = new ClientForm();
                        frame.setVisible(true);
                        ClientMG.getClientMG().setClientForm(frame);
                        
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * Create the frame.
         */
        public ClientForm() {
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(100, 100, 513, 583);
            contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            setContentPane(contentPane);
            contentPane.setLayout(null);
            
            panel = new JPanel();
            panel.setLayout(null);
            panel.setBorder(new TitledBorder(UIManager.getBorder("TitledBorder.border"), "u767Bu5F55u4FE1u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            panel.setBounds(11, 10, 476, 64);
            contentPane.add(panel);
            
            lblIp = new JLabel("IP:");
            lblIp.setHorizontalAlignment(SwingConstants.RIGHT);
            lblIp.setBounds(10, 19, 35, 31);
            panel.add(lblIp);
            
            txtIP = new JTextField();
            txtIP.setText("10.12.50.10");
            txtIP.setColumns(10);
            txtIP.setBounds(55, 22, 97, 24);
            panel.add(txtIP);
            
            label_1 = new JLabel("u7AEFu53E3:");
            label_1.setHorizontalAlignment(SwingConstants.RIGHT);
            label_1.setBounds(154, 19, 35, 31);
            panel.add(label_1);
            
            txtPort = new JTextField();
            txtPort.setText("8899");
            txtPort.setColumns(10);
            txtPort.setBounds(190, 21, 35, 26);
            panel.add(txtPort);
            
            btnLogin = new JButton("u767Bu5F55");
            btnLogin.addActionListener(new BtnLoginActionListener());
            btnLogin.setBounds(337, 22, 65, 25);
            panel.add(btnLogin);
            
            btnExit = new JButton("u9000u51FA");
            btnExit.addActionListener(new BtnExitActionListener());
            btnExit.setBounds(401, 22, 65, 25);
            panel.add(btnExit);
            
            label = new JLabel("u7528u6237u540D:");
            label.setHorizontalAlignment(SwingConstants.RIGHT);
            label.setBounds(228, 19, 50, 31);
            panel.add(label);
            
            txtUser = new JTextField();
            txtUser.setText("visiter");
            txtUser.setColumns(10);
            txtUser.setBounds(281, 22, 50, 26);
            panel.add(txtUser);
            
            panel_1 = new JPanel();
            panel_1.setLayout(null);
            panel_1.setBorder(new TitledBorder(new LineBorder(new Color(184, 207, 229)), "u64CDu4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            panel_1.setBounds(10, 414, 477, 121);
            contentPane.add(panel_1);
            
            btnSend = new JButton("u53D1u9001u6D88u606F");
            btnSend.addActionListener(new BtnSendActionListener());
            btnSend.setBounds(357, 82, 110, 23);
            panel_1.add(btnSend);
            
            scrollPane_1 = new JScrollPane();
            scrollPane_1.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            scrollPane_1.setBounds(10, 24, 457, 48);
            panel_1.add(scrollPane_1);
            
            txtSend = new JTextArea();
            scrollPane_1.setViewportView(txtSend);
            
            sendToAll = new JButton("u7FA4u53D1u6D88u606F");
            sendToAll.addActionListener(new ButtonActionListener());
            sendToAll.setBounds(254, 82, 93, 23);
            panel_1.add(sendToAll);
            
            FileTranbutton = new JButton("u4F20u8F93u6587u4EF6");
            FileTranbutton.addActionListener(new ButtonActionListener_1());
            FileTranbutton.setBounds(10, 82, 81, 23);
            panel_1.add(FileTranbutton);
            
            FileprogressBar = new JProgressBar();
            FileprogressBar.setBounds(98, 92, 146, 8);
            panel_1.add(FileprogressBar);
            
            scrollPane = new JScrollPane();
            scrollPane.setBorder(new TitledBorder(null, "u804Au5929u8BB0u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            scrollPane.setBounds(11, 84, 309, 332);
            contentPane.add(scrollPane);
            
            txtLog = new JTextArea();
            scrollPane.setViewportView(txtLog);
            
            scrollPane_2 = new JScrollPane();
            scrollPane_2.setBorder(new TitledBorder(null, "u5728u7EBFu7528u6237", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            scrollPane_2.setBounds(323, 83, 164, 332);
            contentPane.add(scrollPane_2);
            
            lOnlines = new JList(items);
            scrollPane_2.setViewportView(lOnlines);
        }
        //登录
        private class BtnLoginActionListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                String ip = txtIP.getText().trim();
                int port = Integer.parseInt(txtPort.getText().trim());
                String socketname = txtUser.getText().trim();
                ClientMG.getClientMG().connect(ip, port, socketname);
            }
        }
        //发送信息
        private class BtnSendActionListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                //选中要聊天的用户
                String sendUsername = null;
                if(lOnlines.getSelectedIndex()>=0){
                    //得到用户选择的名称
                    String targetUsername = lOnlines.getSelectedValue().toString();
                    System.out.println(targetUsername);
                    //发送者的名称
                    sendUsername = txtUser.getText().trim();
                    //消息体
                    String sMSG = txtSend.getText();
                    //交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG
                    //包装后的消息发送出去
                    String strSend = "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG;
                    System.out.println(strSend);
                    ClientMG.getClientMG().getClientChat().sendMSG(strSend);
                    ClientMG.getClientMG().setLog("I send To "+targetUsername+":");
                    ClientMG.getClientMG().setLog(sMSG);
                    //清空发送消息框
                    txtSend.setText("");
                }
                
            }
        }
        //推出操作
        private class BtnExitActionListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                //组织推出交互协议"OFFLINE|"+username
                String sendMSG = "OFFLINE|"+txtUser.getText().trim();
                ClientMG.getClientMG().getClientChat().sendMSG(sendMSG);
                //断开与服务器的socket连接
                ClientMG.getClientMG().getClientChat().closeChat();
                ClientMG.getClientMG().clearItems();  //清空列表
                
            }
        }
        private class ButtonActionListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                //发送者的名称
                String sendUsername = txtUser.getText().trim();
                //消息体
                String sMSG = txtSend.getText();
                //交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG
                //包装后的消息发送出去
                String strSend = "MSG|"+sendUsername+"|ALL|"+sMSG;
                System.out.println(strSend);
                //协议为:"MSG|"+sendUsername+"|ALL|"+msg
                ClientMG.getClientMG().getClientChat().sendMSG(strSend);
                txtSend.setText("");
            }
        }
        //传输文件
        private class ButtonActionListener_1 implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                //1从本地选中一个文件,获取其文件相关信息(文件名,文件长度)
                //2创建文件传输的服务器,与服务器接通
                //3组织文件传输交互协议进行传输 
                //FILETRANS|sendername|recname|文件名|文件长度|IP|Port
                
                File finfo = null;
                //用于文件选择的对象jFileChooser
                JFileChooser jFileChooser = new JFileChooser();
                int result = jFileChooser.showOpenDialog(null);
                if(result==JFileChooser.APPROVE_OPTION){
                    finfo = new File(jFileChooser.getSelectedFile().getAbsolutePath());
                    String sFname = finfo.getName();
                    //在用户列表中选择目标用户
                    if(lOnlines.getSelectedIndex()!=-1){
                        String sTarget = lOnlines.getSelectedValue().toString();//得到目标用户
                        String sender = txtUser.getText().trim();
                        //得到新开服务器的IP+Port
                        String IPandPort = ClientMG.getClientMG().CreateFileTranServer(finfo);
                        //组织交互协议串,然后发送    FILETRANS+发送者+目标用户+文件名+文件的长度+IP和端口号
                        String strSend = "FILETRANS|"+sender+"|"+sTarget+"|"+sFname+"|"+finfo.length()+"|"+IPandPort;
                        ClientMG.getClientMG().getClientChat().sendMSG(strSend);
                    }
                }
                
            }
        }
    }
    package rjxy.lkl.Client;
    
    import java.io.File;
    import java.io.IOException;
    import java.net.InetAddress;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    import javax.swing.JOptionPane;
    
    public class ClientMG {
        
    
        //实现管理类的单例化
        private static final ClientMG clientMG = new ClientMG();
        public ClientMG() {
        }
        public static ClientMG getClientMG(){
            return clientMG;
        }
        //操作图形化界面
        ClientForm cWin;
        ClientChat cChat;
        public void setClientForm(ClientForm cf){
            cWin = cf;
        }
    //    设置界面中的消息记录
        public void setLog(String str){
            cWin.txtLog.append(str+"
    ");
        }
        public ClientChat getClientChat(){
            return cChat;
        }
        //新上线的用户添加到JList中
        public void addItem(String username){
            cWin.items.addElement(username);
        }
        public void addItems(String [] sItems){
            for (String username : sItems) {
                addItem(username);
            }
        }
        //一旦断开连接,清空JList中的用户
        //清空单个
        public void removeItem(String str){
            cWin.items.removeElement(str);
        }
        //清空所有
        public void clearItems(){
            cWin.items.clear();
        }
        public void connect(String IP,int port,String Username){
            try {
                Socket socket = new Socket(IP,port);
                ClientMG.getClientMG().setLog("已连接到服务器 ");
                cChat = new ClientChat(socket,Username);
                cChat.start();
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
        FileListener filelistener;
        //创建文件传输的服务器  
        public String CreateFileTranServer(File file){
            try {
                ServerSocket server = new ServerSocket(8881);
                String IP = InetAddress.getLocalHost().getHostAddress();
                filelistener = new FileListener(server,file);
                filelistener.start();
                return IP+"|"+8881;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return "";
            
        }
        //接收文件
        public void recFile(String sender,String fName,int len,String IP,int port){
            //文件名|文件长度|IP|Port
            //4判断是否要接收?  JOptionPane->confirm
            //5同意接收,连接服务器进行文件传输
            //6拒绝接收,向服务器发回拒接接收的消息:FILECANCEL|sendername|recname
            
            JOptionPane msg = new JOptionPane();
            int result = msg.showConfirmDialog(null, sender+"发送文件【"+fName+"】,
    是否接收?", "文件传输确认", JOptionPane.YES_NO_OPTION);
            if(result == JOptionPane.YES_NO_OPTION){
                //确认接收
                try {
                    Socket socket = new Socket(IP,port);
                    new fileRec(socket, fName, len).start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                
            } else{
                //如果拒收   FILECANCEL|FromUser|toUser,sender给我发消息,某某某拒绝了,就通知sender,某某某拒绝了你的文件传输
                String strSend = "FILECANCEL|"+this.getClientChat().UserName+"|"+sender;
                this.getClientChat().sendMSG(strSend);
                this.setLog("您已拒接了"+sender+"的文件传输");
            }
            
        }
        //对方取消文件传递
        public void cancelFileTrans(){
            filelistener.cancelFileTrans();
    //        this.setLog("对方取消了文件传输!!!");
        }
        
    }
    package rjxy.lkl.Client;
    
    import java.io.*;
    import java.net.*;
    
    public class FileListener extends Thread {
        ServerSocket fserver;
        File filetrans;
        public FileListener(ServerSocket fserver, File filetrans) {
            this.fserver = fserver;
            this.filetrans = filetrans;
        }
        //取消传输
        public void cancelFileTrans(){
            if(fserver!=null){
                try {
                    fserver.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        
        public void run() {
            Socket sfile = null;
            DataInputStream dis = null;
            DataOutputStream dos = null;
            try {
                sfile = fserver.accept();
                dis = new DataInputStream(new FileInputStream(filetrans));
                dos = new DataOutputStream(sfile.getOutputStream());
                
                //有关进度条属性的设置
                ClientMG.getClientMG().cWin.FileprogressBar.setValue(0);
                ClientMG.getClientMG().cWin.FileprogressBar.setVisible(true);
                ClientMG.getClientMG().cWin.FileprogressBar.setMaximum((int)filetrans.length());
                
                
                byte[] buff = new byte[1024];
                int iread = 0;
                int len =0;
                while((iread=dis.read(buff, 0, 1024))!=-1){
                    dos.write(buff, 0, iread);  //写文件是,是根据读出的大小进行写入的
                    len += iread;
                    dos.flush();
                    
    //                写入流的同时,设置进度条的进度
                    ClientMG.getClientMG().cWin.FileprogressBar.setValue(len);
                }
                ClientMG.getClientMG().setLog("文件传输完毕!");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    dos.close();
                    dis.close();
                    if(sfile!=null){sfile.close();}
                    if(fserver!=null){fserver.close();}
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    package rjxy.lkl.Client;
    
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.*;
    
    public class fileRec extends Thread{
        Socket socket;
        String sRecFilePath="D:\";
        String fileName;
        int fileLen;
        public fileRec(Socket socket, String fileName, int fileLen) {
            this.socket = socket;
            this.fileName = fileName;
            this.fileLen = fileLen;
        }
        
        public void run() {
            DataInputStream dis = null;
            DataOutputStream dos = null;
            
            //设置进度条属性
            ClientMG.getClientMG().cWin.FileprogressBar.setValue(0);
            ClientMG.getClientMG().cWin.FileprogressBar.setVisible(true);
            ClientMG.getClientMG().cWin.FileprogressBar.setMaximum(fileLen);
            try {
                dis = new DataInputStream(socket.getInputStream());
                dos = new DataOutputStream(new FileOutputStream(sRecFilePath+fileName));
                
                byte[] buff = new byte[1024];
                int iread = 0;
                int len = 0;
                while((iread=dis.read(buff, 0, 1024))!=-1){
                    dos.write(buff, 0, iread);
                    len +=iread;
                    ClientMG.getClientMG().cWin.FileprogressBar.setValue(len);
                    dos.flush();
                }
                ClientMG.getClientMG().setLog("文件接收完毕!");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    dis.close();
                    dos.close();
                    if(socket!=null){ socket.close();}
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        
    }

    服务器端代码:

    package rjxy.lkl.Server;
    
    import java.awt.BorderLayout;
    
    public class ServerForm extends JFrame {
    
        private JPanel contentPane;
        public JPanel panel;
        public JLabel label;
        public JTextField txtPort;
        public JButton btnStart;
        public JButton btnStop;
        public JScrollPane scrollPane;
        public JTextArea txtLog;
        
        
        ServerSocket server;
        ServerListener listener;
        volatile boolean serverFlag;
    
        /**
         * Launch the application.
         */
        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    try {
                        ServerForm frame = new ServerForm();
                        frame.setVisible(true);
                        SocketMG.getsocketMG().setServerForm(frame); //窗体对象传入SocketMG中
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    
        /**
         * Create the frame.
         */
        public ServerForm() {
            setResizable(false);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            setBounds(100, 100, 422, 520);
            contentPane = new JPanel();
            contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
            setContentPane(contentPane);
            contentPane.setLayout(null);
            
            panel = new JPanel();
            panel.setBorder(new TitledBorder(null, "u914Du7F6Eu4FE1u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            panel.setBounds(0, 0, 406, 66);
            contentPane.add(panel);
            panel.setLayout(null);
            
            label = new JLabel("u7AEFu53E3uFF1A");
            label.setBounds(10, 29, 54, 15);
            panel.add(label);
            
            txtPort = new JTextField();
            txtPort.setText("8899");
            txtPort.setBounds(46, 21, 66, 30);
            panel.add(txtPort);
            txtPort.setColumns(10);
            
            btnStart = new JButton("u5F00u59CBu670Du52A1");
            btnStart.addActionListener(new BtnStartActionListener());
            btnStart.setBounds(129, 21, 98, 31);
            panel.add(btnStart);
            
            btnStop = new JButton("u505Cu6B62u670Du52A1");
            btnStop.addActionListener(new BtnStopActionListener());
            btnStop.setBounds(253, 21, 98, 31);
            panel.add(btnStop);
            
            scrollPane = new JScrollPane();
            scrollPane.setBorder(new TitledBorder(null, "u6D88u606Fu8BB0u5F55", TitledBorder.LEADING, TitledBorder.TOP, null, null));
            scrollPane.setBounds(0, 76, 406, 406);
            contentPane.add(scrollPane);
            
            txtLog = new JTextArea();
            scrollPane.setViewportView(txtLog);
        }
        
        //启动Socket服务 
        private class BtnStartActionListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                int port = Integer.parseInt(txtPort.getText().trim());
                try {
                    server = new ServerSocket(port);
                    listener = new ServerListener(server);
                    listener.start();
                    SocketMG.getsocketMG().setLog("服务已开启");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        
        //停止服务
        private class BtnStopActionListener implements ActionListener {
            public void actionPerformed(ActionEvent arg0) {
                SocketMG.getsocketMG().setLog("服务器已关闭");
                //通知所有在线用户服务器关闭消息    交互协议为:"CLOSE|"
                SocketMG.getsocketMG().sendCloseMSGToAll();
                //把OnlineUsers集合中的每一个SocketChat关闭
                SocketMG.getsocketMG().closeALLSocket();
                //ArrayList清空
                SocketMG.getsocketMG().clearList();
                //关闭ServerSocket
                listener.stopListener();
                
                try {
                    if (server != null) {
                        serverFlag = false;
                        server.close();
                    }
                } catch (Exception e2) {
                    // TODO: handle exception
                }
            }
        }
        
    }
    package rjxy.lkl.Server;
    import java.io.IOException;
    import java.net.*;
    
    
    public class ServerListener extends Thread {
        
        ServerSocket server;
        volatile boolean serverFlag;
        public ServerListener(ServerSocket server) {
            this.server = server;
            serverFlag = true;
        }
        //停止监听
        public void stopListener(){
            serverFlag = false;
        }
        public void run() {
            while(serverFlag){
                Socket s = null;
                try {
                    s = server.accept();
                    new SocketChat(s).start();
                    SocketMG.getsocketMG().setLog(s+"已登录");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    package rjxy.lkl.Server;
    import java.net.*;
    import java.io.*;
    public class SocketChat extends Thread {
        
        Socket socket;
        BufferedReader br=null;
        PrintWriter pw = null;
        String UserName;
        public SocketChat(Socket socket) {
            this.socket = socket;
            try {
                br = new BufferedReader(new InputStreamReader(socket.getInputStream(),
                        "UTF-8"));
                pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
                        socket.getOutputStream(), "UTF-8")));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public void sendMSG(String str){
            pw.println(str);
            pw.flush();
        }
        //关闭SocketChat
        public void closeChat(){
            try {
                if (socket != null)
                    socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public void run() {
            try {
                String str = "";
                while((str = br.readLine())!=null){
                    String comm[] = str.split("[|]");
                    if(comm[0].equals("Login")){
                        //读取客户端发过来的用户名
                        String cUsername = comm[1];
                        //赋给服务器端的UserName
                        UserName = cUsername;
                        //①得到所有在线用户发给客户端
                        SocketMG.getsocketMG().sendOnlineUsers(this);
                        //②将当期的socket信息存放在OnLineUsers数组中
                        SocketMG.getsocketMG().addList(this);
                        //③把当前用户信息发送给在线用户
                        SocketMG.getsocketMG().sendNewUsertoAll(this);
                    }else if(comm[0].equals("MSG")){
                        //交互协议 "MSG|"+sendUsername+"|"+targetUsername+"|"+sMSG
                        //取出协议串中的内容
                        String sender = comm[1];
                        
                        String receiver = comm[2];
                        String msg = comm[3];
                        System.out.println("发送者:"+sender+"---接收者:"+receiver+"---消息体:"+msg);
                        if(receiver.equals("ALL")){
                            //"MSG|"+sendUsername+"|ALL|"+msg
                            String strmsg = "MsgReturn|"+sender+"|"+msg;
                            SocketMG.getsocketMG().sendMSGToALL(strmsg, this);
                            SocketMG.getsocketMG().setLog(sender+"发消息给所有人"+"内容为:"+msg);
                        }else{
                            //查询在线集合,如果接收对象则返回这个SocketChat对象
                            SocketChat sc = SocketMG.getsocketMG().getSocketChatByName(receiver);
                            System.out.println("选中的用户的信息:"+sc);
                            if(!(sc==null)){
                                String strmsg = "MsgReturn"+"|"+sender+"|"+msg; //重新组织交换协议
                                System.out.println(strmsg);
                                SocketMG.getsocketMG().sendMSGToSocket(strmsg, sc);
                                SocketMG.getsocketMG().setLog(sender+"发送给"+sc+"的消息是:"+msg);
                            }
                        }
                    }else if(comm[0].equals("OFFLINE")){
                        //用户下线的交互协议:"OFFLINE|"+username
                        //向其他用户发送该用户下线的消息
                        SocketMG.getsocketMG().sendOffLineMSGToAll(this);
                        //移除List中已经下线用户的信息
                        SocketMG.getsocketMG().removeList(this);
                        SocketMG.getsocketMG().setLog(comm[1]+"下线了");
                    } else if(comm[0].equals("FILETRANS")){
    //                    "FILETRANS|"+sender+"|"+sTarget+"|"+sFname+"|"+finfo.length()+"|"+IPandPort
                        String sender = comm[1];
                        SocketChat sTarget = SocketMG.getsocketMG().getSocketChatByName(comm[2]);
                        //sFname+"|"+finfo.length()+"|"+IPandPort
                        String strSend = comm[3]+"|"+comm[4]+"|"+comm[5]+"|"+comm[6];
                        //调用文件发送函数
                        SocketMG.getsocketMG().sendFileTrans(sender, sTarget, strSend);
                        SocketMG.getsocketMG().setLog(sender+"发送了"+strSend+"给"+sTarget);
                    } else if(comm[0].equals("FILECANCEL")){
                        //FILECANCEL|拒收者(A)|被拒收者(B)
                        //得到被拒收者
                        String A = comm[1];
                        SocketChat sc = SocketMG.getsocketMG().getSocketChatByName(comm[2]);
                        //重新组织交互协议  //FILECANCELReturn|拒收者A
                        String strSend = "FILECANCELReturn|"+A;
                        SocketMG.getsocketMG().setLog(A+"拒收了"+comm[2]+"传输的文件");
                        sc.sendMSG(strSend);
                        
                        
                        
                    }
    
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                try {
                    if (br != null)
                        br.close();
                    if (pw != null)
                        pw.close();
                    if (socket != null)
                        socket.close();
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
        }
    }
    package rjxy.lkl.Server;
    
    import java.util.ArrayList;
    
    public class SocketMG {
        
        //实现管理类的单例化
        private static final SocketMG socketMG=new SocketMG();
        private SocketMG(){}
        public static SocketMG getsocketMG(){
            return socketMG;
        }
        SocketChat sChat;
        //操作图形界面
        ServerForm sWin;
        public void setServerForm(ServerForm s){
            sWin=s;
        }
        //设置界面中的消息记录
        public void setLog(String str){
            sWin.txtLog.append(str+"
    ");
        }
        
        //存储socket信息的集合
        private ArrayList<SocketChat> OnLineUsers = new ArrayList<SocketChat>();
        //把新用户添加到集合中
        public synchronized void addList(SocketChat sChat){
            OnLineUsers.add(sChat);
        }
        //得到所有用户在线信息名称,发回给客户端
        public void sendOnlineUsers(SocketChat sc){
            //发送所有用户信息的协议:USERLISTS|user1_user2_user3
            if(OnLineUsers.size()>0){
                String str = "";
                for (int i = 0; i < OnLineUsers.size(); i++) {
                    SocketChat sChat = OnLineUsers.get(i);
                    str += sChat.UserName+"_";
                }
                sc.sendMSG("USERLISTS|"+str);
            }
        }
        //新上线的用户发送给所有在线用户      ADD|用户名
        public void sendNewUsertoAll(SocketChat sc){
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat socketChat = OnLineUsers.get(i);
                //新上线用户这个消息不发给自己,发给其他用户,让其他用户知道该你上线了
                if(!socketChat.equals(sc)){
                    socketChat.sendMSG("ADD|"+sc.UserName);
                }
            }
        }
        //通过用户名查找SocketChat对象
        public SocketChat getSocketChatByName(String name){
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat sChat = OnLineUsers.get(i);
                //此处曾出现过错误,形式为:sChat.equals(name)
                if(sChat.UserName.equals(name)){
                    return sChat;
                }
            }
            return null;
        }
        
        //向目标对象发送消息
        public void sendMSGToSocket(String str,SocketChat sc){
            System.out.println("2222222222222"+str);
            sc.sendMSG(str);     
        }
        //发送消息出自己以外的所有人
        public void sendMSGToALL(String str,SocketChat sc){
            for (int i = 0; i < OnLineUsers.size(); i++) {
                //写程序的时候遇到的问题:SocketChat sChat = OnLineUsers.get(i);  
                //造成了与类成员变量重名,消息只发给自己
                SocketChat socketChat = OnLineUsers.get(i);
    //            if(!socketChat.equals(sc)){
    //                socketChat.sendMSG(str);
    //            }
                socketChat.sendMSG(str);
            }
        }
        //向其他用户发送下线用户下线的通知
        public void sendOffLineMSGToAll(SocketChat sc){
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat socketChat = OnLineUsers.get(i);
                if(!socketChat.equals("sc")){
                    String str = "DEL|"+sc.UserName;
                    socketChat.sendMSG(str);
                }
            }
        }
        //把当前下线的用户从OnLineUsers中清除
        public synchronized void removeList(SocketChat sChat){
            //清除ArrayList中的当前用户信息(socketChat)
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat schat=OnLineUsers.get(i);
                if(schat.equals(sChat)){
                    OnLineUsers.remove(sChat);
                    break;
                }
            }
        }
        //关闭服务器通知给所有在线用户
        public void sendCloseMSGToAll(){
            //组织交互协议为:"CLOSE|"
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat socketchat = OnLineUsers.get(i);
                socketchat.sendMSG("CLOSE|");
            }
        }
        //关闭OnlineUsers中的每一个SocketChat
        public void closeALLSocket(){
            for (int i = 0; i < OnLineUsers.size(); i++) {
                SocketChat socketchat = OnLineUsers.get(i);
                socketchat.closeChat();
            }
        }
        //清空在线集合中的内容
        public void clearList(){
            OnLineUsers.clear();
        }
        //文件传输    发送者,接收者,内容
        public void sendFileTrans(String sender,SocketChat sTarget,String sMSG){
            sTarget.sendMSG("FILETRANS|"+sender+"|"+sMSG);
        }
    }
  • 相关阅读:
    函数式编程
    8 Principles of Better Unit Testing
    COM 组件 V.S. .NET
    WebBrowser 禁用脚本错误提示
    Unable to automatically debug "XXXXX“
    简介
    android中实现跑马灯效果以及AutoCompleteTestView与MultiAutoCompleteTextView的学习
    我的Android六章:Android中SQLite数据库操作
    Android的生命周期学习
    我的Android第五章:通过Intent实现活动与活动之间的交互
  • 原文地址:https://www.cnblogs.com/lkldeblog/p/9093895.html
Copyright © 2011-2022 走看看