📄 udpthread.java
字号:
/**
* @(#)logic.ReciveThread.java 2008-10-9
* Copy Right Information : Tarena
* Project : IPMsg
* JDK version used : jdk1.6.4
* Comments : 接受数据线程类。
* Version : 1.0
* Sr Date Modified By Why & What is modified
* 1. 2008-10-9 小猪 新建
**/
package logic;
import java.awt.SystemTray;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.UnknownHostException;
import java.util.Hashtable;
import javax.swing.JOptionPane;
import data.User;
import frm.IPMsgMainFrm;
import frm.ReceiveNewMSG;
/**
* 接受数据线程类。
* 2008-10-9
* @author 达内科技[Tarena Training Group]
* @version 1.0
* @since JDK1.6(建议)
*/
public class UDPThread extends Thread implements ActionListener {
/** 启动端口 */
public static final int PORT = 3608;
/** 报文长度 */
public static final int messageLength = 8192;
/** 多播组 */
public static InetAddress mcastaddr = null;
/** 多播数据报套接字 - 接受多播组数据 */
private MulticastSocket reciver = null;
/** TCP文件发送Server */
private ServerTCPThread server = null;
/** 飞鸽传书主界面 */
private IPMsgMainFrm ipmsg = null;
/** 程序是否在运行 */
private boolean isRun = true;
/** 发送文件的列表(ip,文件路径[用|分割]) */
private Hashtable<String,String> sendList = new Hashtable<String, String>();
public UDPThread() {
try {
initNet();
} catch (UnknownHostException e) { return;
} catch (IOException e) { return;}
ipmsg = new IPMsgMainFrm();
ipmsg.btnFlush.addActionListener(this);
ipmsg.btnSend.addActionListener(this);
ipmsg.itemQuit.addActionListener(this);
ipmsg.addWindowListener(new MyWindowAdapter());
}
/**
* 初始化网络。
* @throws UnknownHostException 多播地址错误
* @throws IOException 网络端口绑定或加入多播组错误
*/
private void initNet() throws UnknownHostException,IOException{
try {
mcastaddr = InetAddress.getByName("236.232.2.8");
reciver = new MulticastSocket(PORT);
server = new ServerTCPThread(this,PORT);
server.start();
reciver.setTimeToLive(2);
//reciver.setSoTimeout(100*1000);
//System.out.println(reciver.getTimeToLive());
} catch (UnknownHostException e) {
showWrong("地址错误", e);
throw e;
} catch (IOException e) {
showWrong("端口绑定错误", e);
throw e;
}
try {
reciver.joinGroup(mcastaddr);
} catch (IOException e) {
showWrong("加入组播组错误", e);
throw e;
}
}
/**
* 发送消息:
* 消息类型:[hk][10]消息内容
* 消息说明:数据必须以[hk]开头,第二个方括号表示消息的类型,此后表示消息内容
* 10:新用户上线,内容格式:用户名|主机名|IP地址|登录名|优先级
* 11:用户下线,内容格式:IP地址
* 20:对发有消息、文件,内容格式:[2008-10-09 星期四 13:53:51]<[类型]?路径?文件名|[类型][路径]文件名...多个用|分割>此后显示消息内容<br>文件类型说明:0:目录;1:文件
*/
@Override
public void run() {
telGroupIamOnline("[hk][10]");
try {
while(isRun && reciver!=null){
byte[] data = new byte[messageLength];
DatagramPacket packet = new DatagramPacket(data,data.length);
reciver.receive(packet);
dealPacket(packet);
}
} catch (IOException e) {
System.out.println("IO错误:"+e.getMessage());
}
}
/**
* 处理数据包。
* @param packet DatagramPacket包。
*/
private void dealPacket(DatagramPacket packet){
byte[] data = packet.getData();
String xcontent = new String(data);
xcontent = xcontent.trim();
//System.out.println(xcontent);
if(xcontent.startsWith("[hk]") && xcontent.length()>8){
xcontent = xcontent.substring(4);
//System.out.println(xcontent);
String xtype = xcontent.substring(1,3);
int type = 0;
try {
type = Integer.parseInt(xtype);
} catch (NumberFormatException e) {
return;
}
String content = xcontent.substring(4);
//System.out.println(content);
switch (type) {
case 10:
if( ipmsg.model.addUser(User.strToUser(content)))
telUserMyState("[hk][10]",packet.getAddress().getHostAddress());
//telGroupIamOnline("[hk][10]");
break;
case 11:
ipmsg.model.removeFromIP(packet.getAddress().getHostAddress());
break;
case 20:
showContent(content,packet.getAddress().getHostAddress());
break;
}
}
}
/**
* 显示用户发送消息内容和目录.
* @param content
* @param ip
*/
private void showContent(String content,String ip){
if(content.length()>27){
String time = content.substring(1,24);
content = content.substring(25, content.length());
int begin = content.indexOf("<");
int end = content.indexOf(">");
if(begin==-1 || end ==-1)
return;
String path = content.substring(begin+1,end);
content = content.substring(end+1);
new ReceiveNewMSG(time,ipmsg.model.getUserInfo(ip),path,content,ip,PORT);
}
}
/**
* 告诉组播组内的其他用户我的状态。
*/
private void telUserMyState(String begin,String ip){
try {
InetAddress inet = InetAddress.getByName(ip);
User user = User.getSelf();
byte[] data = new byte[messageLength];
data = (begin+user.toString()).getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length,inet,PORT);
reciver.send(packet);
} catch (IOException e) {
System.out.println("发送UDP消息错误:"+e.getMessage());
}
}
/**
* 告诉组播组内的其他用户下线了。
*/
private void telGroupIamOffline(String begin){
try {
User user = User.getSelf();
byte[] data = new byte[messageLength];
data = (begin+user.getIpAdress()).getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length,mcastaddr,PORT);
reciver.send(packet);
} catch (IOException e) {
System.out.println("发送UDP消息错误:"+e.getMessage());
}
}
/**
* 告诉组播组内的其他用户我的状态。
*/
private void telGroupIamOnline(String begin){
try {
User user = User.getSelf();
byte[] data = new byte[messageLength];
data = (begin+user.toString()).getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length,mcastaddr,PORT);
reciver.send(packet);
} catch (IOException e) {
System.out.println("发送UDP消息错误:"+e.getMessage());
}
}
/**
* 告诉组播组内的其他用户我上线了。
*/
private void sendData(String content,String ip){
try {
InetAddress inet = InetAddress.getByName(ip);
byte[] data = content.getBytes();
DatagramPacket packet = new DatagramPacket(data,data.length,inet,PORT);
reciver.send(packet);
} catch (IOException e) {
System.out.println("发送UDP消息错误:"+e.getMessage());
}
}
/**
* 按钮事件。
*/
public void actionPerformed(ActionEvent e) {
if(e.getSource()==ipmsg.btnFlush){
ipmsg.clearTable();
telGroupIamOnline("[hk][10]");
return;
}
if(e.getSource()==ipmsg.btnSend){
int[] rows = ipmsg.getSelectRow();
if(rows.length == 0)return;
for(int row:rows){
String ip = ipmsg.model.getIpAddress(row);
String content = "[hk][20]"+ipmsg.getContent();
addSendList(ip);
sendData(content,ip);
}
ipmsg.clearChat();
ipmsg.clearSendList();
return;
}
if(e.getSource()==ipmsg.itemQuit){
closeIPMsg();
return;
}
}
/**
* 向发送列表中添加向发送文件的列表。
* @param ip
*/
private void addSendList(String ip){
if(sendList.containsKey(ip)){
String value = sendList.get(ip);
value += ipmsg.getSendList();
sendList.put(ip, value);
}else
sendList.put(ip, ipmsg.getSendList());
}
/**
* 检测是否允许向某ip发送某文件。
* @param ip ip地址
* @param path 发送的地址。
* @return true:允许;false:不允许。
*/
public boolean isAllowSend(String ip,String path){
if(sendList.containsKey(ip)){
String value = sendList.get(ip);
if(value.indexOf(path)!=-1)
return true;
}
return false;
}
/**
* 当发送完成某个文件后,从发送列表中删除以发送的文件。
* @param ip ip地址
* @param path 文件或目录路径
* @return 返回删除成功否。
*/
public boolean deleteSendList(String ip,String path){
if(isAllowSend(ip, path)){
String value = sendList.get(ip);
int begin = value.indexOf(path);
if(begin!=-1){
value = value.substring(begin,begin+path.length()+1);
sendList.put(ip, value);
return true;
}
}
return false;
}
/**
* 用JOptionPane显示错误的原因。
* @param msg 错误的简单说明
* @param e 异常.
*/
private void showWrong(String msg,Exception e){
closeAll();
JOptionPane.showMessageDialog(null, msg+":"+e.getMessage(),"错误",JOptionPane.ERROR_MESSAGE);
}
/**
* 关闭所有开启IO
*/
private void closeAll(){
interrupt();
closeUDP();
if(server!=null)
server.closeServer();
}
/**
* 关闭UDP端口
*/
private void closeUDP(){
if(reciver!=null)
reciver.close();
reciver = null;
}
/**
* 退出飞鸽传书。
*/
private void closeIPMsg(){
telGroupIamOffline("[hk][11]");
closeAll();
System.exit(0);
}
/**
* 窗体关闭时触发事件。
*/
private class MyWindowAdapter extends WindowAdapter{
public void windowClosing(WindowEvent e) {
//super.windowClosing(e);
if(SystemTray.isSupported())
ipmsg.dispose();
else
closeIPMsg();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -