有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); } }