91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在java項目中使用MulticastSocket

發布時間:2021-03-25 16:55:24 來源:億速云 閱讀:169 作者:Leah 欄目:編程語言

本篇文章為大家展示了如何在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,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新余市| 韶关市| 达拉特旗| 黄冈市| 濮阳市| 长寿区| 体育| 伊川县| 二连浩特市| 田林县| 抚顺县| 惠来县| 花莲市| 齐河县| 灵山县| 嘉义市| 凤城市| 东阿县| 宜宾市| 九龙城区| 故城县| 新乡县| 平昌县| 柞水县| 临江市| 满城县| 深泽县| 特克斯县| 华阴市| 江津市| 镇江市| 育儿| 罗平县| 乳山市| 常熟市| 韩城市| 隆安县| 宁武县| 泽普县| 敖汉旗| 万盛区|