您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何在java項目中使用MulticastSocket,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
(1)DatagramSocket只允許數據報發給指定的目標地址,而MulticastSocket可以將數據報以廣播的方式發送到多個客戶端。
(2)IP協議為多點廣播提供了這批特殊的IP地址,這些IP地址的范圍是:224.0.0.0至239.255.255.255..
(3)MulticastSocket類時實現多點廣播的關鍵,當MulticastSocket把一個DaragramPocket發送到多點廣播的IP地址時,該數據報將會自動廣播到加入該地址的所有MulticastSocket。MulticastSocket既可以將數據報發送到多點廣播地址,也可以接收其他主機的廣播信息。
(4)事實上,MulticastSocket是DatagramSocket的子類,也就是說,MulticastSocket是特殊的DatagramSocket。當要發送一個數據報時,可以使用隨機端口創建MulticastSocket,也可以在指定端口創建MulticastSocket。MulticastSocket提供了如下三個構造器:
public MulticastSocket() 使用本機默認地址,隨機端口來創建MulticastSocket對象
public MulticastSocket(int portNumber) 用本機默認地址,指定端口來創建MulticastSocket對象
public MulticastSocket(SocketAddress bindaddr) 用指定IP地址,指定端口來創建MulticastSocket對象
(5)創建MulticastSocket對象后,還需要將MulticastSocket加入到指定的多點廣播地址。MulticastSocket使用joinGroup()方法加入指定組;使用leaveGroup()方法脫離一個組。
joinGroup(InetAddress multicastAddr) 將該MulticastSocket加入到指定的多點廣播地址
leaveGroup(InetAddress multicastAddr) 將該MulticastSocket離開指定的多點廣播地址
(6)在某些系統中,可能有多個網絡接口,這可能為多點廣播帶來問題,這時候程序需要在一個指定的網絡接口上監聽,通過調用setInterface()方法可以強制MulticastSocket使用指定的網絡接口‘也可以使用getInterface()方法查詢MulticastSocket監聽的網絡接口。
(7)如果創建僅僅用于發送數據報的MulticastSocket對象,則使用默認地址,隨機端口即可。但如果創建接收用的MulticastSocket對象,'則該MulticastSocket對象必須有指定端口,否則無法確定發送數據報的目標端口。
(8)MulticastSocket用于發送接收數據報的方法與DatagramSocket完全一樣。但MulticastSocket比DatagramSocket多了一個setTimeToLive(int ttl)方法,該ttl用于設置數據報最多可以跨過多少個網絡。
當ttl為0時,指定數據報應停留在本地主機
當ttl為1時,指定數據報發送到本地局域網
當ttl為32時,指定數據報發送到本站點的網絡上
當ttl為64時,意味著數據報應該停留在本地區
當ttl為128時,意味著數據報應保留在本大洲
當ttl為255時,意味著數據報可以發送到所有地方
默認情況下,ttl值為1.
程序實例:
下面程序使用MulticastSocket實現一個基于廣播的多人聊天室。程序只需要一個MulticastSocket,兩個線程,其中MulticastSocket既用于發送,也用于接收;一個線程負責鍵盤輸入,并向MulticastSocket發送數據;一個線程負責從MulticastSocket中讀取數據。
package com.talk; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; import java.net.MulticastSocket; import java.util.Scanner; //讓該類實現Runnable接口,該類的實例可以作為線程的target public class MulticastSocketTest implements Runnable{ //使用常量作為本程序多點廣播的IP地址 private static final String BROADCAST_IP="230.0.0.1"; //使用常量作為本程序的多點廣播的目的地端口 public static final int BROADCAST_PORT=3000; //定義每個數據報大小最大為4kb private static final int DATA_LEN=4096; //定義本程序的MulticastSocket實例 private MulticastSocket socket=null; private InetAddress broadcastAddress=null; private Scanner scan=null; //定義接收網絡數據的字節數組 byte[] inBuff=new byte[DATA_LEN]; //以指定字節數組創建準備接收數據的MulticastSocket對象 private DatagramPacket inPacket =new DatagramPacket(inBuff, inBuff.length); //定義一個用于發送的DatagramPacket對象 private DatagramPacket outPacket=null; public void init() throws IOException{ //創建鍵盤輸入流 Scanner scan=new Scanner(System.in); //創建用于發送、接收數據的MulticastSocket對象,由于該MulticastSocket需要接收數據,所以有指定端口 socket=new MulticastSocket(BROADCAST_PORT); broadcastAddress=InetAddress.getByName(BROADCAST_IP); //將該socket加入到指定的多點廣播地址 socket.joinGroup(broadcastAddress); //設置本MulticastSocket發送的數據報會被回送到自身 socket.setLoopbackMode(false); //初始化發送用的DatagramSocket,它包含一個長度為0的字節數組 outPacket =new DatagramPacket(new byte[0], 0, broadcastAddress, BROADCAST_PORT); //啟動本實例的run()方法作為線程執行體的線程 new Thread(this).start(); //不斷的讀取鍵盤輸入 while(scan.hasNextLine()){ //將鍵盤輸入的一行字符轉換成字節數組 byte [] buff=scan.nextLine().getBytes(); //設置發送用的DatagramPacket里的字節數據 outPacket.setData(buff); //發送數據報 socket.send(outPacket); } socket.close(); } public void run() { // TODO Auto-generated method stub while(true){ //讀取Socket中的數據,讀到的數據放入inPacket所封裝的字節組里 try { socket.receive(inPacket); //打印從socket讀取到的內容 System.out.println("聊天信息:"+new String(inBuff,0,inPacket.getLength())); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } if(socket!=null){ //讓該socket離開多點IP廣播地址 try { socket.leaveGroup(broadcastAddress); //關閉socket對象 socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.exit(1); } } public static void main(String[] args) { try { new MulticastSocketTest().init(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
下面將結合MulticastSocket和DatagramSocket開發一個簡單的局域網即時通訊工具,局域網內每個用戶啟動該工具后,就可以看到該局域網內所有的在線用戶,該用戶也會被其他用戶看到:
該程序的思路是:每個用戶都啟動兩個Socket,即MulticastSocket和DatagramSocket。其中MulticastSocket會周期性的向230.0.0.1發送在線信息,且所有的MulticastSocket都會加入到230.0.0.1這個多點廣播IP中,這樣每個用戶都會收到其他用戶的在線信息,如果系統在一段時間內沒有收到某個用戶廣播的在線信息,則從用戶列表中刪除該用戶。除此之外,該MulticastSocket還用于向其他用戶發送廣播信息。
DatagramSocket主要用于發送私聊信息,當用戶收到其他用戶廣播來的DatagramSocket時,即可獲得該用戶MulticastSocket對應的SocketAddress.這個SocketAddress將作為發送私聊信息的重要依據。—本程序讓MulticastSocket在30000端口監聽,而DatagramSocket在30001端口監聽,這樣程序就可以根據其他用戶廣播來的DatagramPacket得到他的DatagramSocket所在的地址。
本系統提供了一個UserInfo類,該類封裝了用戶名、圖標、對應的SocketAddress以及該用戶對應的交談窗口,失去聯系的次數等信息:
package com.talk; import java.net.SocketAddress; import com.bank.ChatFrame; public class UserInfo { // 該用戶的圖標 private String icon; // 該用戶的名字 private String name; // 該用戶的MulitcastSocket所在的IP和端口 private SocketAddress address; // 該用戶失去聯系的次數 private int lost; // 該用戶對應的交談窗口 private ChatFrame chatFrame; public UserInfo(){} // 有參數的構造器 public UserInfo(String icon , String name , SocketAddress address , int lost) { this.icon = icon; this.name = name; this.address = address; this.lost = lost; } // 省略所有成員變量的setter和getter方法 // icon的setter和getter方法 public void setIcon(String icon) { this.icon = icon; } public String getIcon() { return this.icon; } // name的setter和getter方法 public void setName(String name) { this.name = name; } public String getName() { return this.name; } // address的setter和getter方法 public void setAddress(SocketAddress address) { this.address = address; } public SocketAddress getAddress() { return this.address; } // lost的setter和getter方法 public void setLost(int lost) { this.lost = lost; } public int getLost() { return this.lost; } // chatFrame的setter和getter方法 public void setChatFrame(ChatFrame chatFrame) { this.chatFrame = chatFrame; } public ChatFrame getChatFrame() { return this.chatFrame; } // 使用address作為該用戶的標識,所以根據address作為 // 重寫hashCode()和equals方法的標準 public int hashCode() { return address.hashCode(); } public boolean equals(Object obj) { if (obj != null && obj.getClass() == UserInfo.class) { UserInfo target = (UserInfo)obj; if (address != null) { return address.equals(target.getAddress()); } } return false; } }
通過UserInfo的封裝,所有客戶端只需要維護該UserInfo類的列表,程序就可以實現廣播、發送私聊信息等功能。本程序的底層通信類則需要一個MulticastSocket和一個DatagramSocket,該工具類的代碼如下:
package com.talk; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.SocketAddress; import java.util.ArrayList; import javax.swing.JOptionPane; public class ComUtil { // 定義本程序通信所使用的字符集 public static final String CHARSET = "utf-8"; // 使用常量作為本程序的多點廣播IP地址 private static final String BROADCAST_IP = "230.0.0.1"; // 使用常量作為本程序的多點廣播目的的端口 // DatagramSocket所用的的端口為該端口+1。 public static final int BROADCAST_PORT = 30000; // 定義每個數據報的最大大小為4K private static final int DATA_LEN = 4096; // 定義本程序的MulticastSocket實例 private MulticastSocket socket = null; // 定義本程序私聊的Socket實例 private DatagramSocket singleSocket = null; // 定義廣播的IP地址 private InetAddress broadcastAddress = null; // 定義接收網絡數據的字節數組 byte[] inBuff = new byte[DATA_LEN]; // 以指定字節數組創建準備接受數據的DatagramPacket對象 private DatagramPacket inPacket = new DatagramPacket(inBuff , inBuff.length); // 定義一個用于發送的DatagramPacket對象 private DatagramPacket outPacket = null; // 聊天的主界面程序 private LanTalk lanTalk; // 構造器,初始化資源 public ComUtil(LanTalk lanTalk) throws Exception { this.lanTalk = lanTalk; // 創建用于發送、接收數據的MulticastSocket對象 // 因為該MulticastSocket對象需要接收,所以有指定端口 socket = new MulticastSocket(BROADCAST_PORT); // 創建私聊用的DatagramSocket對象 singleSocket = new DatagramSocket(BROADCAST_PORT + 1); broadcastAddress = InetAddress.getByName(BROADCAST_IP); // 將該socket加入指定的多點廣播地址 socket.joinGroup(broadcastAddress); // 設置本MulticastSocket發送的數據報被回送到自身 socket.setLoopbackMode(false); // 初始化發送用的DatagramSocket,它包含一個長度為0的字節數組 outPacket = new DatagramPacket(new byte[0] , 0 , broadcastAddress , BROADCAST_PORT); // 啟動兩個讀取網絡數據的線程 new ReadBroad().start(); Thread.sleep(1); new ReadSingle().start(); } // 廣播消息的工具方法 public void broadCast(String msg) { try { // 將msg字符串轉換字節數組 byte[] buff = msg.getBytes(CHARSET); // 設置發送用的DatagramPacket里的字節數據 outPacket.setData(buff); // 發送數據報 socket.send(outPacket); } // 捕捉異常 catch (IOException ex) { ex.printStackTrace(); if (socket != null) { // 關閉該Socket對象 socket.close(); } JOptionPane.showMessageDialog(null , "發送信息異常,請確認30000端口空閑,且網絡連接正常!" , "網絡異常", JOptionPane.ERROR_MESSAGE); System.exit(1); } } // 定義向單獨用戶發送消息的方法 public void sendSingle(String msg , SocketAddress dest) { try { // 將msg字符串轉換字節數組 byte[] buff = msg.getBytes(CHARSET); DatagramPacket packet = new DatagramPacket(buff , buff.length , dest); singleSocket.send(packet); } // 捕捉異常 catch (IOException ex) { ex.printStackTrace(); if (singleSocket != null) { // 關閉該Socket對象 singleSocket.close(); } JOptionPane.showMessageDialog(null , "發送信息異常,請確認30001端口空閑,且網絡連接正常!" , "網絡異常", JOptionPane.ERROR_MESSAGE); System.exit(1); } } // 不斷從DatagramSocket中讀取數據的線程 class ReadSingle extends Thread { // 定義接收網絡數據的字節數組 byte[] singleBuff = new byte[DATA_LEN]; private DatagramPacket singlePacket = new DatagramPacket(singleBuff , singleBuff.length); public void run() { while (true) { try { // 讀取Socket中的數據。 singleSocket.receive(singlePacket); // 處理讀到的信息 lanTalk.processMsg(singlePacket , true); } // 捕捉異常 catch (IOException ex) { ex.printStackTrace(); if (singleSocket != null) { // 關閉該Socket對象 singleSocket.close(); } JOptionPane.showMessageDialog(null , "接收信息異常,請確認30001端口空閑,且網絡連接正常!" , "網絡異常", JOptionPane.ERROR_MESSAGE); System.exit(1); } } } } // 持續讀取MulticastSocket的線程 class ReadBroad extends Thread { public void run() { while (true) { try { // 讀取Socket中的數據。 socket.receive(inPacket); // 打印輸出從socket中讀取的內容 String msg = new String(inBuff , 0 , inPacket.getLength() , CHARSET); // 讀到的內容是在線信息 if (msg.startsWith(YeekuProtocol.PRESENCE) && msg.endsWith(YeekuProtocol.PRESENCE)) { String userMsg = msg.substring(2 , msg.length() - 2); String[] userInfo = userMsg.split(YeekuProtocol .SPLITTER); UserInfo user = new UserInfo(userInfo[1] , userInfo[0] , inPacket.getSocketAddress(), 0); // 控制是否需要添加該用戶的旗標 boolean addFlag = true; ArrayList<Integer> delList = new ArrayList<>(); // 遍歷系統中已有的所有用戶,該循環必須循環完成 for (int i = 1 ; i < lanTalk.getUserNum() ; i++ ) { UserInfo current = lanTalk.getUser(i); // 將所有用戶失去聯系的次數加1 current.setLost(current.getLost() + 1); // 如果該信息由指定用戶發送過來 if (current.equals(user)) { current.setLost(0); // 設置該用戶無須添加 addFlag = false; } if (current.getLost() > 2) { delList.add(i); } } // 刪除delList中的所有索引對應的用戶 for (int i = 0; i < delList.size() ; i++) { lanTalk.removeUser(delList.get(i)); } if (addFlag) { // 添加新用戶 lanTalk.addUser(user); } } // 讀到的內容是公聊信息 else { // 處理讀到的信息 lanTalk.processMsg(inPacket , false); } } // 捕捉異常 catch (IOException ex) { ex.printStackTrace(); if (socket != null) { // 關閉該Socket對象 socket.close(); } JOptionPane.showMessageDialog(null , "接收信息異常,請確認30000端口空閑,且網絡連接正常!" , "網絡異常", JOptionPane.ERROR_MESSAGE); System.exit(1); } } } } }
本程序的一個主類,LanTalk ,該類使用DefaultListModel來維護用戶列表,該類里的每個列表項就是一個UserInfo。該類還提供了一個ImageCellRenderer,該類用于將列表項繪制出用戶圖標和用戶名字。
package com.talk; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.net.DatagramPacket; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.text.DateFormat; import java.util.Date; import javax.swing.DefaultListModel; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.ListCellRenderer; import com.bank.ChatFrame; import com.bank.LoginFrame; public class LanTalk extends JFrame { private DefaultListModel<UserInfo> listModel = new DefaultListModel<>(); // 定義一個JList對象 private JList<UserInfo> friendsList = new JList<>(listModel); // 定義一個用于格式化日期的格式器 private DateFormat formatter = DateFormat.getDateTimeInstance(); public LanTalk() { super("局域網聊天"); // 設置該JList使用ImageCellRenderer作為單元格繪制器 friendsList.setCellRenderer(new ImageCellRenderer()); listModel.addElement(new UserInfo("all" , "所有人" , null , -2000)); friendsList.addMouseListener(new ChangeMusicListener()); add(new JScrollPane(friendsList)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(2, 2, 160 , 600); } // 根據地址來查詢用戶 public UserInfo getUserBySocketAddress(SocketAddress address) { for (int i = 1 ; i < getUserNum() ; i++) { UserInfo user = getUser(i); if (user.getAddress() != null && user.getAddress().equals(address)) { return user; } } return null; } // ------下面四個方法是對ListModel的包裝------ // 向用戶列表中添加用戶 public void addUser(UserInfo user) { listModel.addElement(user); } // 從用戶列表中刪除用戶 public void removeUser(int pos) { listModel.removeElementAt(pos); } // 獲取該聊天窗口的用戶數量 public int getUserNum() { return listModel.size(); } // 獲取指定位置的用戶 public UserInfo getUser(int pos) { return listModel.elementAt(pos); } // 實現JList上的鼠標雙擊事件的監聽器 class ChangeMusicListener extends MouseAdapter { public void mouseClicked(MouseEvent e) { // 如果鼠標的擊鍵次數大于2 if (e.getClickCount() >= 2) { // 取出鼠標雙擊時選中的列表項 UserInfo user = (UserInfo)friendsList.getSelectedValue(); // 如果該列表項對應用戶的交談窗口為null if (user.getChatFrame() == null) { // 為該用戶創建一個交談窗口,并讓該用戶引用該窗口 user.setChatFrame(new ChatFrame(null , user)); } // 如果該用戶的窗口沒有顯示,則讓該用戶的窗口顯示出來 if (!user.getChatFrame().isShowing()) { user.getChatFrame().setVisible(true); } } } } /** * 處理網絡數據報,該方法將根據聊天信息得到聊天者, * 并將信息顯示在聊天對話框中。 * @param packet 需要處理的數據報 * @param single 該信息是否為私聊信息 */ public void processMsg(DatagramPacket packet , boolean single) { // 獲取該發送該數據報的SocketAddress InetSocketAddress srcAddress = (InetSocketAddress) packet.getSocketAddress(); // 如果是私聊信息,則該Packet獲取的是DatagramSocket的地址, // 將端口減1才是對應的MulticastSocket的地址 if (single) { srcAddress = new InetSocketAddress(srcAddress.getHostName() , srcAddress.getPort() - 1); } UserInfo srcUser = getUserBySocketAddress(srcAddress); if (srcUser != null) { // 確定消息將要顯示到哪個用戶對應窗口上。 UserInfo alertUser = single ? srcUser : getUser(0); // 如果該用戶對應的窗口為空,顯示該窗口 if (alertUser.getChatFrame() == null) { alertUser.setChatFrame(new ChatFrame(null , alertUser)); } // 定義添加的提示信息 String tipMsg = single ? "對您說:" : "對大家說:"; try{ // 顯示提示信息 alertUser.getChatFrame().addString(srcUser.getName() + tipMsg + "......................(" + formatter.format(new Date()) + ")\n" + new String(packet.getData() , 0 , packet.getLength() , ComUtil.CHARSET) + "\n"); } catch (Exception ex) { ex.printStackTrace(); } if (!alertUser.getChatFrame().isShowing()) { alertUser.getChatFrame().setVisible(true); } } } // 主方法,程序的入口 public static void main(String[] args) { LanTalk lanTalk = new LanTalk(); new LoginFrame(lanTalk , "請輸入用戶名、頭像后登錄"); } } // 定義用于改變JList列表項外觀的類 class ImageCellRenderer extends JPanel implements ListCellRenderer<UserInfo> { private ImageIcon icon; private String name; // 定義繪制單元格時的背景色 private Color background; // 定義繪制單元格時的前景色 private Color foreground; @Override public Component getListCellRendererComponent(JList list , UserInfo userInfo , int index , boolean isSelected , boolean cellHasFocus) { // 設置圖標 icon = new ImageIcon("ico/" + userInfo.getIcon() + ".gif"); name = userInfo.getName(); // 設置背景色、前景色 background = isSelected ? list.getSelectionBackground() : list.getBackground(); foreground = isSelected ? list.getSelectionForeground() : list.getForeground(); // 返回該JPanel對象作為單元格繪制器 return this; } // 重寫paintComponent方法,改變JPanel的外觀 public void paintComponent(Graphics g) { int imageWidth = icon.getImage().getWidth(null); int imageHeight = icon.getImage().getHeight(null); g.setColor(background); g.fillRect(0, 0, getWidth(), getHeight()); g.setColor(foreground); // 繪制好友圖標 g.drawImage(icon.getImage() , getWidth() / 2 - imageWidth / 2 , 10 , null); g.setFont(new Font("SansSerif" , Font.BOLD , 18)); // 繪制好友用戶名 g.drawString(name, getWidth() / 2 - name.length() * 10 , imageHeight + 30 ); } // 通過該方法來設置該ImageCellRenderer的最佳大小 public Dimension getPreferredSize() { return new Dimension(60, 80); } }
除了以上主要的代碼,還有YeekuProtocol ChatFrame LoginFrame等類:
package com.talk; public interface YeekuProtocol { String PRESENCE = "⊿⊿"; String SPLITTER = "▓"; }
package com.bank; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JComponent; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; import com.talk.ComUtil; import com.talk.LanTalk; import com.talk.YeekuProtocol; // 登錄用的對話框 public class LoginFrame extends JDialog { public JLabel tip; public JTextField userField = new JTextField("錢鐘書" , 20); public JComboBox<Integer> iconList = new JComboBox<>( new Integer[]{1, 2, 3, 4, 5 , 6, 7, 8 ,9 ,10}); private JButton loginBn = new JButton("登錄"); // 聊天的主界面 private LanTalk chatFrame; // 聊天通信的工具實例 public static ComUtil comUtil; // 構造器,用于初始化的登錄對話框 public LoginFrame(LanTalk parent , String msg) { super(parent , "輸入名字后登錄" , true); this.chatFrame = parent; setLayout(new GridLayout(5, 1)); JPanel jp = new JPanel(); tip = new JLabel(msg); tip.setFont(new Font("Serif" , Font.BOLD , 16)); jp.add(tip); add(jp); add(getPanel("用戶名" , userField)); iconList.setPreferredSize(new Dimension(224, 20)); add(getPanel("圖 標" , iconList)); JPanel bp = new JPanel(); loginBn.addActionListener(new MyActionListener(this)); bp.add(loginBn); add(bp); pack(); setVisible(true); } // 工具方法,該方法將一個字符串和組件組合成JPanel對象 private JPanel getPanel(String name , JComponent jf) { JPanel jp = new JPanel(); jp.add(new JLabel(name + ":")); jp.add(jf); return jp; } // 該方法用于改變登錄窗口最上面的提示信息 public void setTipMsg(String tip) { this.tip.setText(tip); } // 定義一個事件監聽器 class MyActionListener implements ActionListener { private LoginFrame loginFrame; public MyActionListener(LoginFrame loginFrame) { this.loginFrame = loginFrame; } // 當鼠標單擊事件發生時 public void actionPerformed(ActionEvent evt) { try { // 初始化聊天通信類 comUtil = new ComUtil(chatFrame); final String loginMsg = YeekuProtocol.PRESENCE + userField.getText() + YeekuProtocol.SPLITTER + iconList.getSelectedObjects()[0] + YeekuProtocol.PRESENCE; comUtil.broadCast(loginMsg); // 啟動定時器每20秒廣播一次在線信息 javax.swing.Timer timer = new javax.swing.Timer(1000 * 10 , event-> comUtil.broadCast(loginMsg)); timer.start(); loginFrame.setVisible(false); chatFrame.setVisible(true); } catch (Exception ex) { loginFrame.setTipMsg("確認30001端口空閑,且網絡正常!"); } } } }
package com.bank; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.net.InetSocketAddress; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.KeyStroke; import com.talk.LanTalk; import com.talk.UserInfo; // 定義交談的對話框 public class ChatFrame extends JDialog { // 聊天信息區 JTextArea msgArea = new JTextArea(12 , 45); // 聊天輸入區 JTextField chatField = new JTextField(30); // 發送聊天信息的按鈕 JButton sendBn = new JButton("發送"); // 該交談窗口對應的用戶 UserInfo user; // 構造器,用于初始化交談對話框的界面 public ChatFrame(LanTalk parent , final UserInfo user) { super(parent , "和" + user.getName() + "聊天中" , false); this.user = user; msgArea.setEditable(false); add(new JScrollPane(msgArea)); JPanel buttom = new JPanel(); buttom.add(new JLabel("輸入信息:")); buttom.add(chatField); buttom.add(sendBn); add(buttom , BorderLayout.SOUTH); // 發送消息的Action,Action是ActionListener的子接口 Action sendAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent evt) { InetSocketAddress dest = (InetSocketAddress)user.getAddress(); // 在聊友列表中,所有人項的SocketAddress是null // 這表明是向所有人發送消息 if (dest == null) { LoginFrame.comUtil.broadCast(chatField.getText()); msgArea.setText("您對大家說:" + chatField.getText() + "\n" + msgArea.getText()); } // 向私人發送信息 else { // 獲取發送消息的目的 dest = new InetSocketAddress(dest.getHostName(), dest.getPort() + 1); LoginFrame.comUtil.sendSingle(chatField.getText(), dest); msgArea.setText("您對" + user.getName() + "說:" + chatField.getText() + "\n" + msgArea.getText()); } chatField.setText(""); } }; sendBn.addActionListener(sendAction); // 將Ctrl+Enter鍵和"send"關聯 chatField.getInputMap().put(KeyStroke.getKeyStroke('\n' , java.awt.event.InputEvent.CTRL_MASK) , "send"); // 將"send"與sendAction關聯 chatField.getActionMap().put("send", sendAction); pack(); } // 定義向聊天區域添加消息的方法 public void addString(String msg) { msgArea.setText(msg + "\n" + msgArea.getText()); } }
上述內容就是如何在java項目中使用MulticastSocket,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。