?? comutil.java
字號:
import java.awt.*;
import java.net.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
/**
* Description:該類用于網絡通信,它包含了MulticastSocket實例和
* DatagramSocket實例,分別實現廣播和私聊功能
*
* <br/>Copyright (C), 2008-2010, Yeeku.H.Lee
* <br/>This program is protected by copyright laws.
* <br/>Program Name:
* <br/>Date:
* @author Yeeku.H.Lee kongyeeku@163.com
* @version 1.0
*/
//聊天交換信息的工具類
public class ComUtil
{
//使用常量作為本程序的多點廣播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 LanChat lanTalk;
//構造器,初始化資源
public ComUtil(LanChat lanTalk)throws IOException , InterruptedException
{
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();
//設置發送用的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();
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中的數據,讀到的數據放在inPacket所封裝的字節數組里。
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中的數據,讀到的數據放在inPacket所封裝的字節數組里。
socket.receive(inPacket);
//打印輸出從socket中讀取的內容
String msg = new String(inBuff , 0 , inPacket.getLength());
//讀到的內容是在線信息
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<Integer>();
//遍歷系統中已有的所有用戶,該循環必須循環完成
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);
}
}
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -