基于UDP的多播(组播)文件传输

此次的课程设计通过借鉴网上的信息(前人种树后人乘凉,感谢在网上分享的大佬们)然后自己再次修改调试完成。

步入正题吧

主要代码:

public class MULTICAST {

	private String cachePath="D:\\Network\\CC1\\";
	SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//设置日期格式
	public String BC_IP;// = "228.5.6.7"; // 组播地址
	public int BC_PORT;// = 4567; // 组播端口
	private final static int PACK_SIZE = 1024;
	private byte[] buffer = new byte[PACK_SIZE];
	
	public String msg=null;
	public String input=null;
	private InetAddress bcAddr = null;
	private MulticastSocket sock=null;// 接收文件来显提示
	private MulticastSocket socket1=null;// 接收文件信息
	String filename = null;
	int fileLen = 0;
	int numofBlock = 0;
	int lastSize = 0;
	
	MULTICAST(){}
	
	MULTICAST(String addr,String port){
		
		BC_IP=addr;
		BC_PORT=Integer.parseInt(port);
		
		try {
			/*实例化InetAddress,指定接收地址*/
			sock = new MulticastSocket(BC_PORT);
			socket1 = new MulticastSocket(BC_PORT + 1);
			socket2 = new MulticastSocket(BC_PORT + 2);
			/*(绑定多点广播套接字)创建一个用于接收的MulticastSocket组播套接字对象*/
			bcAddr = InetAddress.getByName(BC_IP);
			/*使用组播套接字joinGroup(),将其加入到一个组播*/
			sock.joinGroup(bcAddr);
			socket1.joinGroup(bcAddr);

			sock.setTimeToLive(1);
			  
			msg="启动!<启动时间:" + new Date() + ">";
			Received.textArea.setText(msg+"\n");
			rev();
			
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
	}
	
	public void rev() throws IOException{
		new Thread(() -> {
		while (sock!=null) {
			try {
				//
				byte filetipBuf[] = new byte[256];// 防止文件名字过长(此处最长256个字符)
				DatagramPacket packet_tip = new DatagramPacket(filetipBuf,0, filetipBuf.length);
				sock.receive(packet_tip);
				String str_filetip = new String(packet_tip.getData(), 0,packet_tip.getLength());
				filename = str_filetip.substring(8);
				//Received.textArea.append(df.format(new Date())+str_filetip + "\n");				
				// 接收文件长度(字节数)
				byte[] fileLenBuf = new byte[12];// 可以传输1T的文件
				DatagramPacket packet_len = new DatagramPacket(fileLenBuf,fileLenBuf.length);
				socket1.receive(packet_len);
				String str_fileLen = new String(fileLenBuf, 0,packet_len.getLength());
				fileLen = Integer.parseInt(str_fileLen);
				//Received.textArea.append(df.format(new Date())+"文件大小: " + fileLen + "字节, " + (float)(fileLen / 1024) + "kb, " + (float)(fileLen / 1024 / 1024) + "Mb\n");
				//
				DatagramPacket packet_file = new DatagramPacket(buffer, 0,buffer.length);
				numofBlock = fileLen / buffer.length;// 循环次数(将该文件分成了多少块)
				lastSize = fileLen % buffer.length;// 最后一点点零头的字节数
				File file = new File(cachePath + filename);
				FileOutputStream fos = new FileOutputStream(file);// 从内存取出存入文件
				for (int i = 0; i < numofBlock; i++) {
					packet_file = new DatagramPacket(buffer, 0,
							buffer.length);
					socket1.receive(packet_file);// 通过套接字接收数据
					fos.write(buffer, 0, 1024);// 写入文件
				}
				// 接收最后一点点零头
				packet_file = new DatagramPacket(buffer, 0, lastSize);
				socket1.receive(packet_file);// 通过套接字接收数据
				fos.write(buffer, 0, lastSize);// 写入文件
				fos.close();
				
				Received.textArea.append(df.format(new Date())+str_filetip + "\n");
				Received.textArea.append(df.format(new Date())+"文件大小: " + fileLen + "字节, " + (float)(fileLen / 1024) + "kb, " + (float)(fileLen / 1024 / 1024) + "Mb\n");
				// 反馈包
			} catch (Exception e) {
				System.out.println(e);
			}
		}
		}).start();
	}
	
	
	public void run(File file0) throws IOException {	
		try {
			File file = file0;
			try {
				// 将文件名发送过去
				String str_filename = file.getName();
				String str_tip = "有文件,请处理:" + str_filename;
				byte[] fileNameBuf = str_tip.getBytes();
				MulticastSocket socket = new MulticastSocket();
				DatagramPacket packet = new DatagramPacket(fileNameBuf, fileNameBuf.length,bcAddr, BC_PORT);
				socket.send(packet);
				socket.close();
				//
				FileInputStream fis = new FileInputStream(
						file);// 从文件中取出写入内存
				// 将文件长度发送过去
				int fileLen = fis.available();
				String str_len = "" + fileLen;
				byte[] fileLenBuf = str_len.getBytes();
				socket = new MulticastSocket();
				packet = new DatagramPacket(fileLenBuf,fileLenBuf.length, bcAddr,BC_PORT+1);
				socket.send(packet);
				socket.close();
				
				// 发送文件主体
				byte[] buf = new byte[1024];
				int numofBlock = fileLen / buf.length;// 循环次数(将该文件分成了多少块)
				int lastSize = fileLen % buf.length;// 最后一点点零头的字节数
				socket = new MulticastSocket();
				for (int i = 0; i < numofBlock; i++) {
					fis.read(buf, 0, buf.length);// 写入内存
					packet = new DatagramPacket(buf,buf.length, bcAddr,BC_PORT+1);
					socket.send(packet);
					Thread.sleep(1); // 简单的防止丢包现象
				}
				// 发送最后一点点零头
				fis.read(buf, 0, lastSize);
				packet = new DatagramPacket(buf,buf.length, bcAddr,BC_PORT+1);
				socket.send(packet);
				Thread.sleep(1); // 简单的防止丢包现象
				fis.close();
				socket.close();
				Received.textArea.append(df.format(new Date())+" 文件传输完毕!"+"\n");
				Received.textField.setText("");
			} catch (Exception ev) {
				System.out.println(ev);
			}
		} catch (Exception ex) {
			JOptionPane.showMessageDialog(null,"打开文档出错!");
		}
	}
	
	public void save_as() {
		// 选择要接收的文件
		JFileChooser filechooser = new JFileChooser();
		int result = filechooser.showSaveDialog(null);
		if (result == JFileChooser.APPROVE_OPTION) {
			try {
				File file2 = filechooser.getSelectedFile();
				String file2Name=file2.getName();
				try {
					File file1 = new File(cachePath + "\\" + file2Name);
					saveAs(file1, file2);
					//
					Received.textArea.append(df.format(new Date())+" 文件接收完毕!"+"\n");
					Received.textArea.append(df.format(new Date())+" 文件已处理!!"+"\n");
				} catch (Exception ex) {
					System.out.println(ex);
				}
			} catch (Exception ex) {
				JOptionPane.showMessageDialog(null,"打开保存出错!");
			}
		}
	}
	
	public void saveAs(File file1, File file2) {// 把file1另存为file2,并删掉file1
		try {
			FileInputStream fis = new FileInputStream(file1);
			FileOutputStream fos = new FileOutputStream(file2);
			byte buf[] = new byte[1024];
			int len = 0;
			while ((len = fis.read(buf)) != -1) {
				fos.write(buf, 0, len);
			}
			fis.close();
			fos.close();
			file1.delete();
		} catch (Exception ex) {
			System.out.println(ex);
		}
	}
	
	public void leave() throws IOException {
		sock.leaveGroup(bcAddr);
		socket1.leaveGroup(bcAddr);
		socket2.leaveGroup(bcAddr);
	}
	
	public void exit0() throws IOException {
		sock.close();
		socket1.close();
		socket2.close();
	}

}

运行结果展示:

发送端:

基于UDP的多播(组播)文件传输_第1张图片

接收端:

基于UDP的多播(组播)文件传输_第2张图片

接收文件后:

基于UDP的多播(组播)文件传输_第3张图片

总结:完成了UDP多播文件传输,但是没有考虑和完成可靠传输的问题。关于多播文件传输时遇到主机之间传输失败的问题请看我的另一篇文章https://blog.csdn.net/TanCairo/article/details/89410340。

END!!!

你可能感兴趣的:(UDP网络编程)