熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

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

2013-11-23 19:39:15  來源: Java核心技術 

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

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

  程序清單codes///LanChat/LanChatjava

  public class LanChat extends JFrame

  {

  private DefaultListModel listModel = new DefaultListModel()

  //定義一個JList對象

  private JList friendsList = new JList(listModel)

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

  private DateFormat formatter = DateFormatgetDateTimeInstance()

  public LanChat()

  {

  super(局域網聊天

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

  friendsListsetCellRenderer(new ImageCellRenderer())

  listModeladdElement(new UserInfo(all 所有人 null ))

  friendsListaddMouseListener(new ChangeMusicListener())

  add(new JScrollPane(friendsList))

  setDefaultCloseOperation(JFrameEXIT_ON_CLOSE)

  setBounds(

  }

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

  public void addUser(UserInfo user)

  {

  listModeladdElement(user)

  }

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

  public void removeUser(int pos)

  {

  listModelremoveElementAt(pos)

  }

  //根據地址來查詢用戶

  public UserInfo getUserBySocketAddress(SocketAddress address)

  {

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

  {

  UserInfo user = getUser(i)

  if (usergetAddress() != null &&

  usergetAddress()equals(address))

  {

  return user;

  }

  }

  return null;

  }

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

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

  public int getUserNum()

  {

  return listModelsize()

  }

  //獲取指定位置的用戶

  public UserInfo getUser(int pos)

  {

  return (UserInfo)listModelelementAt(pos)

  }

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

  class ChangeMusicListener extends MouseAdapter

  {

  public void mouseClicked(MouseEvent e)

  {

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

  if (egetClickCount() >=

  {

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

  UserInfo user = (UserInfo)friendsListgetSelectedValue()

  //如果該列表項對應用戶的交談窗口為null

  if (usergetChatFrame() == null)

  {

  //為該用戶創建一個交談窗口並讓該用戶引用該窗口

  usersetChatFrame(new ChatFrame(null user))

  }

  //如果該用戶的窗口沒有顯示則讓該用戶的窗口顯示出來

  if (!usergetChatFrame()isShowing())

  {

  usergetChatFrame()setVisible(true)

  }

  }

  }

  }

  /**

  * 處理網絡數據報該方法將根據聊天信息得到聊天者

  * 並將信息顯示在聊天對話框中

  * @param packet 需要處理的數據報

  * @param single 該信息是否為私聊信息

  */

  public void processMsg(DatagramPacket packet boolean single)

  {

  //獲取該發送該數據報的SocketAddress

  InetSocketAddress srcAddress = (InetSocketAddress)packetgetSocket

  Address()

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

  //對應的MulticastSocket的地址

  if (single)

  {

  srcAddress = new InetSocketAddress(srcAddressgetHostName()

  srcAddressgetPort()

  }

  UserInfo srcUser = getUserBySocketAddress(srcAddress)

  if (srcUser != null)

  {

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

  UserInfo alertUser = single ? srcUser : getUser(

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

  if (alertUsergetChatFrame() == null)

  {

  alertUsersetChatFrame(new ChatFrame(null alertUser))

  }

  //定義添加的提示信息

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

  //顯示提示信息

  alertUsergetChatFrame()addString(srcUsergetName() + tipMsg

  + ……( + formatterformat(new Date()) + )\n

  + new String(packetgetData() packetgetLength()) + \n

  if (!alertUsergetChatFrame()isShowing())

  {

  alertUsergetChatFrame()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/ + userInfogetIcon() + gif

  name = userInfogetName()

  background = isSelected ? listgetSelectionBackground() : listgetBack

  ground()

  foreground = isSelected ? listgetSelectionForeground() : list

  getForeground()

  //返回該JPanel對象作為單元格繪制器

  return this;

  }

  //重寫paintComponent方法改變JPanel的外觀

  public void paintComponent(Graphics g)

  {

  int imageWidth = icongetImage()getWidth(null)

  int imageHeight = icongetImage()getHeight(null)

  gsetColor(background)

  gfillRect( getWidth() getHeight())

  gsetColor(foreground)

  //繪制好友圖標

  gdrawImage(icongetImage() getWidth() / imageWidth / null)

  gsetFont(new Font(SansSerif FontBOLD ))

  //繪制好友用戶名

  gdrawString(name getWidth() / namelength() * imageHeight +

  }

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

  public Dimension getPreferredSize()

  {

  return new Dimension(

  }

  }

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

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

       返回目錄瘋狂Java講義

       編輯推薦

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

       新手學Java 編程

       Java程序設計培訓視頻教程


From:http://tw.wingwit.com/Article/program/Java/hx/201311/27255.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.