⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 udpthread.java

📁 局域网飞鸽传输
💻 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 + -