java實現(xiàn)多人聊天系統(tǒng)
本文實例為大家分享了java實現(xiàn)多人聊天系統(tǒng)的具體代碼,供大家參考,具體內(nèi)容如下
開發(fā)環(huán)境
Windows 7 操作系統(tǒng)
MyEclipse
聊天室程序結(jié)構(gòu)設(shè)計
1.系統(tǒng)分為客戶端、服務(wù)器端和連接服務(wù)器客戶端三個模塊。
2.客戶端負(fù)責(zé)發(fā)送消息。
3.服務(wù)器端負(fù)責(zé)接收客戶端發(fā)來的信息并執(zhí)行相應(yīng)操作處理,最后通過群發(fā)功能,使客戶端將群聊的消息的顯示出來。
4.連接服務(wù)器端負(fù)責(zé)連接服務(wù)器,從而進(jìn)入客戶端。
總體模塊圖
客戶端代碼
Client.java
package servlet; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.net.Socket; import java.net.UnknownHostException; import java.io.OutputStreamWriter; public class Client { ? ? ? ? ? ? ? Socket socket; ? ? ? ? ? ? ? BufferedWriter bw; ? ? ? ? ? ? ? BufferedReader br ; ?? ??? ? public Client(String ip, int port){ ? ? ? ? ?try { ? ? ? ? ? ? ? socket =new Socket(ip,port); ? ? ? ? ? ? ? bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); ?? ? ? ? ? ? ?br=new BufferedReader(new InputStreamReader(socket.getInputStream())); ? ? ? ? ? ? ? }catch (UnknownHostException e){ ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? }catch(IOException e){ ? ? ? ? ? ? ? e.printStackTrace(); ? ? ? ? ? ? ? ? } ? ? } public void sendMessage(String message) { ? ? ? ? ? try{? ? ? ? ? ? ? ? bw.write(message); ? ? ? ? ? ? ? bw.newLine(); ? ? ? ? ? ? ? bw.flush(); ? ? ? ?}catch(IOException e){ ? ? ? ? ? ? ?e.printStackTrace(); ?? ? ? ? ?} ? ?} public String reciveMessage() { ? ? ? ?String message=null; ? ? ? ?try {? ? ? ?? ? ? message = br.readLine(); ? ? ? }catch(IOException e) { ? ? ? ? ? e.printStackTrace(); ? ? ? } ? ? return message; } public void close(){ ?? ? try{ ?? ? socket.close(); ?? ?}catch(IOException e){ ?? ?e.printStackTrace(); ?? ?} }}
ClientFrame.java
package servlet; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.text.SimpleDateFormat; import java.util.Date; import javax.swing.*; import javax.swing.border.EmptyBorder; public class ClientFrame extends JFrame { ? ? private JPanel contentPane; ? ? private JLabel lblUserName; ? ? private JTextField tfMessage; ? ? private JButton btnSend; ? ? private JTextArea textArea; ? ? private String userName; ? ? private Client client; public ClientFrame(String ip,String userName){ ? ? this.userName = userName; ? ? init();//添加窗體初始化內(nèi)容 ? ? addListener(); ? ? client=new Client(ip,8080); ? ? ReadMessageThread t=new ReadMessageThread(); ? ? t.start(); } private class ReadMessageThread extends Thread{ ? ? ?public void run() { ?? ? ?while(true) { ?? ??? ? ?String str=client.reciveMessage(); ?? ??? ? ?textArea.append(str+"\n");//添加文本內(nèi)容 ?? ? ?} ? } ?? } private void init(){ ? ?setTitle("客戶端"); ? ?setResizable(false); ? ?setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ? ?setBounds(100,100,450,300); ? ?contentPane = new JPanel(); ? ?contentPane.setBorder(new EmptyBorder(5,5,5,5)); ? ?contentPane.setLayout(null); ? ?setContentPane(contentPane); ? ?JScrollPane scrollPane = new JScrollPane(); ? ?scrollPane.setBounds(5,5,434,229); ? ?contentPane.add(scrollPane); ? textArea =new JTextArea(); ? scrollPane.setViewportView(textArea); ? textArea .setEditable(false); ? JPanel panel =new JPanel(); ? panel.setBounds(5,235,434,32); ? contentPane.add(panel); ? panel.setLayout(null); ? lblUserName = new JLabel(userName); ? lblUserName.setHorizontalAlignment(SwingConstants.TRAILING); ? lblUserName.setBounds(2,4,55,22); ? panel.add(lblUserName); ? tfMessage =new JTextField(); ? tfMessage.setBounds(62,5,274,22); ? tfMessage.setColumns(10); ? panel.add(tfMessage); ? btnSend =new JButton("發(fā)送"); ? btnSend.setBounds(336,4,93,23); ? panel.add(btnSend); ? tfMessage.validate(); } private void addListener(){ ?btnSend.addActionListener(new ActionListener(){ ? public void actionPerformed(ActionEvent e){ ? ? ? ? Date date=new Date(); ?? ??? ?SimpleDateFormat sf=new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); ? ? ? ? client.sendMessage(userName+""+sf.format(date)+":\n"+tfMessage.getText()); ?? ??? ?tfMessage.setText("");//清空 ? ? ? ? ? } ? ? ? }); ? ?this.addWindowListener(new WindowAdapter(){//開啟窗口監(jiān)聽 ?? ?public void windowClosing(WindowEvent atg0) { ?? ??? ?int op = JOptionPane.showConfirmDialog(ClientFrame.this,"確定要退出聊天室嗎?","確定",JOptionPane.YES_NO_OPTION); ?? ??? ?if(op == JOptionPane.YES_OPTION) { ?? ??? ? ? ?client.sendMessage("%EXIT%:" + userName); ?? ??? ??? ?try { ?? ??? ??? ??? ?Thread.sleep(200); ?? ??? ??? ??? ? ?? ??? ??? ?}catch(InterruptedException e) { ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ?} ?? ??? ??? ?client.close(); ? ? ? ? ? ? System.exit(0); ?? ??? ?} ? ? ? ? ?} ? ? ? }); ? } }
LinkServerFrame.java
package servlet; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.*; import javax.swing.border.EmptyBorder; @SuppressWarnings("serial") public class LinkServerFrame extends JFrame { ?? ?private JPanel contentPane;//下方面板 ? ? private JLabel lblIP; ? ? private JLabel lblUserName; ? ? private JTextField tfIP; ? ? private JTextField tfUserName; ? ? private JButton btnLink; ? ?public LinkServerFrame(){ ?? ?setTitle("連接服務(wù)器"); ?? ?setResizable(false); ?? ?setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ?? ?setBounds(100, 100, 390, 150); ? ?contentPane = new JPanel(); ? ?contentPane.setBorder(new EmptyBorder(5,5,5,5)); ? ?contentPane.setLayout(null); ? ?setContentPane(contentPane); ? ?lblIP =new JLabel("服務(wù)器IP地址:"); ? ?lblIP.setFont(new Font("微軟雅黑",Font.PLAIN,14)); ? ?lblIP.setBounds(20,15,100,15); ? ?contentPane.add(lblIP); ? ?tfIP =new JTextField("127.0.0.1"); ? ?tfIP.setBounds(121,13,242,21); ? ?contentPane.add(tfIP); ? ?tfIP.setColumns(10); ? ?lblUserName = new JLabel("用戶名:"); ? lblUserName.setFont(new Font("微軟雅黑",Font.PLAIN,14)); ? lblUserName.setBounds(60,40,60,15); ? ?contentPane.add(lblUserName); ? ?tfUserName =new JTextField(); ? tfUserName.setBounds(121,42,242,21); ? contentPane.add(tfUserName); ? tfUserName.setColumns(10); ? btnLink =new JButton("連接服務(wù)器"); ? btnLink.addActionListener(new ActionListener(){ ? ? ? ? public void actionPerformed(ActionEvent e){ ?? ? ?do_btnlink_actionPerformed(e); ? } ? ?}); ? btnLink.setFont(new Font("微軟雅黑",Font.PLAIN,14)); ? ?btnLink.setBounds(140,80,120,23); ? ?contentPane.add(btnLink);//顯示連接服務(wù)器窗口 ?} public static void main(String[] args){ ? ? ?LinkServerFrame linkServerFrame = new LinkServerFrame(); ? ? ?linkServerFrame.setVisible(true); } ? protected void do_btnlink_actionPerformed(ActionEvent e) { ?? ? ?if(!tfIP.getText().equals("")&&!tfUserName.getText().equals("")) {//文本框的內(nèi)容不能為空 ?? ??? ? ?dispose();//銷毀當(dāng)前窗口 ?? ??? ? ClientFrame clientFrame=new ClientFrame(tfIP.getText().trim(), tfUserName.getText().trim()); ?? ??? ? ?clientFrame.setVisible(true);//顯示客戶窗體 ?? ? ?} ?? ? ?else { ?? ??? ? ?JOptionPane.showMessageDialog(null,"文本框里的內(nèi)容不能為空!","警告",JOptionPane.WARNING_MESSAGE); ?? ? ?} ? ? ? ?} }
服務(wù)器端代碼
Server.java
package servlet; import java.net.ServerSocket; import java.net.Socket; import java.util.HashSet; import java.io.BufferedWriter; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; public class Server { ? ?private HashSet<Socket> allSocket; ? ?private ServerSocket server; ?public Server() { ?? ? try { ?? ??? ?server = new ServerSocket(8080); ? }catch(IOException e) { ?? ? ?e.printStackTrace(); ? } ?? ? allSocket=new HashSet<Socket>(); ?}? ?public void startServer() throws IOException{ ?? ? while(true) { ? ? ? ? ?Socket socket =server.accept(); ?? ??? ? System.out.println("用戶已經(jīng)進(jìn)入聊天室"); ?? ??? ? allSocket.add(socket); ? ? ? ? ?ServerThread t= new ServerThread(socket); ? ? ? ? ?t.start(); ?? ??? ? ?? ? } ?} ?private class ServerThread extends Thread{ ?? ? ? Socket socket; ?? ? public ServerThread(Socket socket) { ? ? ? ?this.socket=socket; ?? ? } ? ? public void run() { ?? ??? ? BufferedReader br=null; ?? ??? ? try { ?? ??? ??? ?br=new BufferedReader(new InputStreamReader(socket.getInputStream())); ?? ??? ??? ?while(true) { ?? ??? ??? ??? ?String str=br.readLine(); ?? ??? ??? ??? ?if(str.contains("%EXIT%")) { ? ? ? ? ? ? ??? ? String tmp=str.split(":")[1]+"用戶退出聊天室"; ? ? ? ? ? ? ? ? ?sendMessageToALLClient(tmp); ? ? ? ? ? ? ? ? ?allSocket.remove(socket); ? ? ? ? ? ? ? ? ?socket.close(); ? ? ? ? ? ? ? ? ?return;?? ? ?? ??? ??? ??? ?} ?? ??? ??? ??? ?sendMessageToALLClient(str); ?? ??? ??? ?} ?? ??? ? }catch(IOException e) { ?? ??? ??? ??? ?e.printStackTrace(); ?? ??? ??? ? ?? ??? ? } ?? ? }} ?? ?private void sendMessageToALLClient(String str) throws IOException { ?? ?for(Socket s: allSocket) { ?? ??? ?try{ ?? ? ? ?BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(s.getOutputStream())); ?? ??? ?bw.write(str); ?? ??? ?bw.newLine(); ? ? ? ? bw.flush(); ?? ?}catch(IOException e) { ?? ??? ?e.printStackTrace(); ?? ??? ??? ? ?? ??? ? } ?? ?} ?} ?public static void main(String[] args) { ?? ? Server s = new Server(); ?? ? try { ?? ??? ? s.startServer(); ?? ? }catch(IOException e){ ?? ??? ? e.printStackTrace(); ?? ? } ?? ? } ?}
操作步驟
1.先運行服務(wù)器端代碼(server.java)建立連接,然后運行客戶端(LinkServerFrame.java)輸入用戶名
2.登入成功之后會顯示用戶已經(jīng)進(jìn)入聊天室
3.進(jìn)入多人聊天室
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot+@EnableScheduling使用定時器的常見案例
項目開發(fā)中經(jīng)常需要執(zhí)行一些定時任務(wù),本文主要介紹了SpringBoot+@EnableScheduling使用定時器的常見案例,具有一定的參考價值,感興趣的可以了解一下2023-09-09IDEA最新版2020.1的maven工程本地依賴倉庫無法使用問題(已解決)
這篇文章主要介紹了IDEA最新版2020.1的maven工程本地依賴倉庫無法使用問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06關(guān)于ObjectUtils.isEmpty()?和?null?的區(qū)別
這篇文章主要介紹了關(guān)于ObjectUtils.isEmpty()?和?null?的區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02SpringMVC的注解@RequestMapping屬性及使用
這篇文章主要為大家介紹了SpringMVC注解@RequestMapping屬性及使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05使用Get方式提交數(shù)據(jù)到Tomcat服務(wù)器的方法
這篇文章將介紹向服務(wù)器發(fā)送數(shù)據(jù),并且服務(wù)器將數(shù)據(jù)的處理結(jié)果返回給客戶端,本文給大家介紹使用Get方式向服務(wù)器發(fā)送數(shù)據(jù),感興趣的朋友一起學(xué)習(xí)吧2016-04-04Springboot內(nèi)外部logback多環(huán)境配置詳解
本文主要介紹了Springboot內(nèi)外部logback多環(huán)境配置詳解,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01Mybatis游標(biāo)查詢大量數(shù)據(jù)方式
這篇文章主要介紹了Mybatis游標(biāo)查詢大量數(shù)據(jù)方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-02-02