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"), "\u767B\u5F55\u4FE1\u606F", 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("\u7AEF\u53E3:");
        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("\u767B\u5F55");
        btnLogin.addActionListener(new BtnLoginActionListener());
        btnLogin.setBounds(337, 22, 65, 25);
        panel.add(btnLogin);
        
        btnExit = new JButton("\u9000\u51FA");
        btnExit.addActionListener(new BtnExitActionListener());
        btnExit.setBounds(401, 22, 65, 25);
        panel.add(btnExit);
        
        label = new JLabel("\u7528\u6237\u540D:");
        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)), "\u64CD\u4F5C", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        panel_1.setBounds(10, 414, 477, 121);
        contentPane.add(panel_1);
        
        btnSend = new JButton("\u53D1\u9001\u6D88\u606F");
        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("\u7FA4\u53D1\u6D88\u606F");
        sendToAll.addActionListener(new ButtonActionListener());
        sendToAll.setBounds(254, 82, 93, 23);
        panel_1.add(sendToAll);
        
        FileTranbutton = new JButton("\u4F20\u8F93\u6587\u4EF6");
        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, "\u804A\u5929\u8BB0\u5F55", 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, "\u5728\u7EBF\u7528\u6237", 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+"\r\n");
    }
    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+"】,\r\n是否接收?", "文件傳輸確認", 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, "\u914D\u7F6E\u4FE1\u606F", TitledBorder.LEADING, TitledBorder.TOP, null, null));
        panel.setBounds(0, 0, 406, 66);
        contentPane.add(panel);
        panel.setLayout(null);
        
        label = new JLabel("\u7AEF\u53E3\uFF1A");
        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("\u5F00\u59CB\u670D\u52A1");
        btnStart.addActionListener(new BtnStartActionListener());
        btnStart.setBounds(129, 21, 98, 31);
        panel.add(btnStart);
        
        btnStop = new JButton("\u505C\u6B62\u670D\u52A1");
        btnStop.addActionListener(new BtnStopActionListener());
        btnStop.setBounds(253, 21, 98, 31);
        panel.add(btnStop);
        
        scrollPane = new JScrollPane();
        scrollPane.setBorder(new TitledBorder(null, "\u6D88\u606F\u8BB0\u5F55", 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+"\r\n");
    }
    
    //存儲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);
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM