當前位置:編程學習大全網 - 源碼下載 - 瘋狂Java講義:使用MulticastSocket實現多點廣播(4)

瘋狂Java講義:使用MulticastSocket實現多點廣播(4)

 該類主要實現底層的網絡通信功能 在該類中提供了壹個broadCast方法 該方法使用MulticastSocket將指定字符串廣播到所有客戶端 還提供了sendSingle方法 該方法使用DatagramSocket將指定字符串發送到指定SocketAddress 如程序中前兩行粗體字代碼所示 除此之外 該類裏還提供了 個內部線程類 ReadSingle和ReadBroad 這兩個線程類采用循環不斷讀取DatagramSocket和MulticastSocket中的數據 如果讀到的信息是廣播來的在線信息 則保持該用戶在線 如果讀到的是用戶的聊天信息 則直接將該信息顯示出來

 在該類中用到了本程序的壹個主類 LanChat 該類使用DefaultListModel來維護用戶列表 該類裏的每個列表項就是壹個UserInfo 該類還提供了壹個ImageCellRenderer 該類用於將列表項繪制出用戶圖標和用戶名字

 程序清單 codes/ / /LanChat/LanChat java

 public class LanChat extends JFrame

 {

 private DefaultListModel listModel = new DefaultListModel()

 //定義壹個JList對象

 private JList friendsList = new JList(listModel)

 //定義壹個用於格式化日期的格式器

 private DateFormat formatter = DateFormat getDateTimeInstance()

 public LanChat()

 {

 super( 局域網聊天 )

 //設置該JList使用ImageCellRenderer作為單元格繪制器

 friendsList setCellRenderer(new ImageCellRenderer())

 listModel addElement(new UserInfo( all 所有人 null ))

 friendsList addMouseListener(new ChangeMusicListener())

 add(new JScrollPane(friendsList))

 setDefaultCloseOperation(JFrame EXIT_ON_CLOSE)

 setBounds( )

 }

 //向用戶列表中添加用戶

 public void addUser(UserInfo user)

 {

 listModel addElement(user)

 }

 //從用戶列表中刪除用戶

 public void removeUser(int pos)

 {

 listModel removeElementAt(pos)

 }

 //根據地址來查詢用戶

 public UserInfo getUserBySocketAddress(SocketAddress address)

 {

 for (int i = ; i < getUserNum() ; i++)

 {

 UserInfo user = getUser(i)

 if (user getAddress() != null &&

 user getAddress() equals(address))

 {

 return user;

 }

 }

 return null;

 }

 // 下面兩個方法是對ListModel的包裝

 //獲取該聊天窗口的用戶數量

 public int getUserNum()

 {

 return listModel size()

 }

 //獲取指定位置的用戶

 public UserInfo getUser(int pos)

 {

 return (UserInfo)listModel elementAt(pos)

 }

 //實現JList上的鼠標雙擊監聽器

 class ChangeMusicListener extends MouseAdapter

 {

 public void mouseClicked(MouseEvent e)

 {

 //如果鼠標的擊鍵次數大於

 if (e getClickCount() >= )

 {

 //取出鼠標雙擊時選中的列表項

 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 getSocket

 Address()

 //如果是私聊信息 則該Packet獲取的是DatagramSocket的地址 將端口減 才是

 //對應的MulticastSocket的地址

 if (single)

 {

 srcAddress = new InetSocketAddress(srcAddress getHostName()

 srcAddress getPort() )

 }

 UserInfo srcUser = getUserBySocketAddress(srcAddress)

 if (srcUser != null)

 {

 //確定消息將要顯示到哪個用戶對應窗口上

 UserInfo alertUser = single ? srcUser : getUser( )

 //如果該用戶對應的窗口為空 顯示該窗口

 if (alertUser getChatFrame() == null)

 {

 alertUser setChatFrame(new ChatFrame(null alertUser))

 }

 //定義添加的提示信息

 String tipMsg = single ? 對您說 : 對大家說 ;

 //顯示提示信息

 alertUser getChatFrame() addString(srcUser getName() + tipMsg

 + ……( + formatter format(new Date()) + )\n

 + new String(packet getData() packet getLength()) + \n )

 if (!alertUser getChatFrame() isShowing())

 {

 alertUser getChatFrame() setVisible(true)

 }

 }

 }

 //主方法 程序的入口

 public static void main(String[] args)

 {

 LanChat lc = new LanChat()

 new LoginFrame(lc 請輸入用戶名 頭像後登錄 )

 }

 }

 //定義用於改變JList列表項外觀的類

 class ImageCellRenderer extends JPanel implements ListCellRenderer

 {

 private ImageIcon icon;

 private String name;

 //定義繪制單元格時的背景色

 private Color background;

 //定義繪制單元格時的前景色

 private Color foreground;

 public Component getListCellRendererComponent(JList list Object value int

 index ? boolean isSelected boolean cellHasFocus)

 {

 UserInfo userInfo = (UserInfo)value;

 icon = new ImageIcon( ico/ + userInfo getIcon() + gif )

 name = userInfo getName()

 background = isSelected ? list getSelectionBackground() : list getBack

 ground()

 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( getWidth() getHeight())

 g setColor(foreground)

 //繪制好友圖標

 g drawImage(icon getImage() getWidth() / imageWidth / null)

 g setFont(new Font( SansSerif Font BOLD ))

 //繪制好友用戶名

 g drawString(name getWidth() / name length() * imageHeight + )

 }

 //通過該方法來設置該ImageCellRenderer的最佳大小

 public Dimension getPreferredSize()

 {

 return new Dimension( )

 }

 }

 上面類中提供的addUser和removeUser方法用於暴露給通信類ComUtil使用 用於向用戶列表中添加 刪除用戶 除此之外 該類還提供了壹個processMsg方法 該方法用於處理網絡中讀取的數據報 將數據報中的內容取出 並顯示在特定的窗口中

 上面講解的只是本程序的關鍵類 本程序還涉及YeekuProtocol ChatFrame LoginFrame等類 由於篇幅關系 此處不再給出這些類的源代碼 讀者可以參考codes/ / /LanTalk路徑下的源代碼

? 返回目錄 瘋狂Java講義

? 編輯推薦

? Java程序性能優化 讓妳的Java程序更快 更穩定

? 新手學Java 編程

lishixinzhi/Article/program/Java/hx/201311/27255

  • 上一篇:java中編寫冒泡排序算法 bubbleSort(int[]arr)
  • 下一篇:關於二進制原碼反碼補碼的問題
  • copyright 2024編程學習大全網