通过该UserInfo类的封装这样所有客户端只需要维护该UserInfo类的列表程序就可以实现广播发送私聊信息等功能本程序底层通信的工具类则需要一个MulticastSocket和一个DatagramSocket该工具类的代码如下
程序清单codes///LanTalk/ComUtiljava
//聊天交换信息的工具类
public class ComUtil
{
//使用常量作为本程序的多点广播IP地址
private static final String BROADCAST_IP
= ;
//使用常量作为本程序的多点广播目的的端口
//DatagramSocket所用的的端口为该端口
public static final int BROADCAST_PORT = ;
//定义每个数据报的最大大小为K
private static final int DATA_LEN = ;
//定义本程序的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 inBufflength)
//定义一个用于发送的DatagramPacket对象
private DatagramPacket outPacket = null;
//聊天的主界面
private LanChat lanTalk;
//构造器初始化资源
public ComUtil(LanChat lanTalk)throws IOException InterruptedException
{
thislanTalk = lanTalk;
//创建用于发送接收数据的MulticastSocket对象
//因为该MulticastSocket对象需要接收所以有指定端口
socket = new MulticastSocket(BROADCAST_PORT)
//创建私聊用的DatagramSocket对象
singleSocket = new DatagramSocket(BROADCAST_PORT + )
broadcastAddress = InetAddressgetByName(BROADCAST_IP)
//将该socket加入指定的多点广播地址
socketjoinGroup(broadcastAddress)
//设置本MulticastSocket发送的数据报被回送到自身
socketsetLoopbackMode(false)
//初始化发送用的DatagramSocket它包含一个长度为的字节数组
outPacket = new DatagramPacket(new byte[]
broadcastAddress BROADCAST_PORT)
//启动两个读取网络数据的线程
new ReadBroad()start()
Threadsleep()
new ReadSingle()start()
}
//广播消息的工具方法
public void broadCast(String msg)
{
try
{
//将msg字符串转换字节数组
byte[] buff = msggetBytes()
//设置发送用的DatagramPacket里的字节数据
outPacketsetData(buff)
//发送数据报
socketsend(outPacket)
}
//捕捉异常
catch (IOException ex)
{
exprintStackTrace()
if (socket != null)
{
//关闭该Socket对象
socketclose()
}
JOptionPaneshowMessageDialog(null
发送信息异常请确认端口空闲且网络连接正常!
网络异常 JOptionPaneERROR_MESSAGE)
Systemexit()
}
}
//定义向单独用户发送消息的方法
public void sendSingle(String msg SocketAddress dest)
{
try
{
//将msg字符串转换字节数组
byte[] buff = msggetBytes()
DatagramPacket packet = new DatagramPacket(
buff bufflength dest)
singleSocketsend(packet)
}
//捕捉异常
catch (IOException ex)
{
exprintStackTrace()
if (singleSocket != null)
{
//关闭该Socket对象
singleSocketclose()
}
JOptionPaneshowMessageDialog(null
发送信息异常请确认端口空闲且网络连接正常!
网络异常 JOptionPaneERROR_MESSAGE)
Systemexit()
}
}
//不断从DatagramSocket中读取数据的线程
class ReadSingle extends Thread
{
//定义接收网络数据的字节数组
byte[] singleBuff = new byte[DATA_LEN];
private DatagramPacket singlePacket =
new DatagramPacket(singleBuff singleBufflength)
public void run()
{
while (true)
{
try
{
//读取Socket中的数据读到的数据放在inPacket所封装的字节数组里
singleSocketreceive(singlePacket)
//处理读到的信息
lanTalkprocessMsg(singlePacket true)
}
//捕捉异常
catch (IOException ex)
{
exprintStackTrace()
if (singleSocket != null)
{
//关闭该Socket对象
singleSocketclose()
}
JOptionPaneshowMessageDialog(null
接收信息异常请确认端口空闲且网络连接正常!
网络异常 JOptionPaneERROR_MESSAGE)
Systemexit()
}
}
}
}
//持续读取MulticastSocket的线程
class ReadBroad extends Thread
{
public void run()
{
while (true)
{
try
{
//读取Socket中的数据读到的数据放在inPacket所封装的字节数组里
socketreceive(inPacket)
//打印输出从socket中读取的内容
String msg = new String(inBuff inPacketgetLength())
//读到的内容是在线信息
if (msgstartsWith(YeekuProtocolPRESENCE)
&& msgendsWith(YeekuProtocolPRESENCE))
{
String userMsg = msgsubstring( msglength() )
String[] userInfo = userMsgsplit(YeekuProtocolSPLITTER)
UserInfo user = new UserInfo(userInfo[] userInfo[]
inPacketgetSocketAddress() )
//控制是否需要添加该用户的旗标
boolean addFlag = true;
ArrayList<Integer> delList = new ArrayList<Integer>()
//遍历系统中已有的所有用户该循环必须循环完成
for (int i = ; i < lanTalkgetUserNum() ; i++ )
{
UserInfo current = lanTalkgetUser(i)
//将所有用户失去联系的次数加
currentsetLost(currentgetLost() + )
//如果该信息由指定用户发送过来
if (currentequals(user))
{
currentsetLost()
//设置该用户无须添加
addFlag = false;
}
if (currentgetLost() > )
{
delListadd(i)
}
}
//删除delList中的所有索引对应的用户
for (int i = ; i < delListsize() ; i++)
{
lanTalkremoveUser(delListget(i))
}
if (addFlag)
{
//添加新用户
lanTalkaddUser(user)
}
}
//读到的内容是公聊信息
else
{
//处理读到的信息
lanTalkprocessMsg(inPacket false)
}
}
//捕捉异常
catch (IOException ex)
{
exprintStackTrace()
if (socket != null)
{
//关闭该Socket对象
socketclose()
}
JOptionPaneshowMessageDialog(null
接收信息异常请确认端口空闲且网络连接正常!
网络异常 JOptionPaneERROR_MESSAGE)
Systemexit()
}
}
}
}
}
返回目录疯狂Java讲义
编辑推荐
Java程序性能优化让你的Java程序更快更稳定
新手学Java 编程
Java程序设计培训视频教程