UDP:Java实现简单大文件传输

今天闲来无事,想起过几天要写一个UDP文件传输的插件服务,于是下午就动手写了个UDP文件传输的小代码. 个人觉得还挺有意思的,对UDP感兴趣的小伙伴可以参考看看哦.

好了,下面直接上代码.

1.UDPServer.java

复责接收文件,保存.

package com.bill.udp.server;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import com.bill.udp.util.UDPUtils;

/**
 * Test file transfer of Server 
 * @author Bill  QQ:593890231
 * @since v1.0 2014/09/21
 * 
 */
public class UDPServer {
	
	private static final String SAVE_FILE_PATH = "E:/2013.mkv";
	
	public static void main(String[] args) {
		
		byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
		
		DatagramPacket dpk = null;
		DatagramSocket dsk = null;
		BufferedOutputStream bos = null;
		try {
			
			dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("localhost"), UDPUtils.PORT));
			dsk = new DatagramSocket(UDPUtils.PORT + 1, InetAddress.getByName("localhost"));
			bos = new BufferedOutputStream(new FileOutputStream(SAVE_FILE_PATH));
			System.out.println("wait client ....");
			dsk.receive(dpk);
			
			int readSize = 0;
			int readCount = 0;
			int flushSize = 0;
			while((readSize = dpk.getLength()) != 0){
				// validate client send exit flag  
				if(UDPUtils.isEqualsByteArray(UDPUtils.exitData, buf, readSize)){
					System.out.println("server exit ...");
					// send exit flag 
					dpk.setData(UDPUtils.exitData, 0, UDPUtils.exitData.length);
					dsk.send(dpk);
					break;
				}
				
				bos.write(buf, 0, readSize);
				if(++flushSize % 1000 == 0){ 
					flushSize = 0;
					bos.flush();
				}
				dpk.setData(UDPUtils.successData, 0, UDPUtils.successData.length);
				dsk.send(dpk);
				
				dpk.setData(buf,0, buf.length);
				System.out.println("receive count of "+ ( ++readCount ) +" !");
				dsk.receive(dpk);
			}
			
			// last flush 
			bos.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally{
			try {
				if(bos != null)
					bos.close();
				if(dsk != null)
					dsk.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		
	}
}

2.UDPClient.java

读取文件,并发送数据包传输文件

package com.bill.udp.client;

import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import com.bill.udp.util.UDPUtils;
/**
 * Test File transfer of Client
 * @author Bill QQ:593890231
 * @since v1.0 2014/09/21
 */
public class UDPClient {
	
	private static final String SEND_FILE_PATH = "D:/2013.mkv";
	
	public static void main(String[] args){
		long startTime = System.currentTimeMillis();
		
		byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
		byte[] receiveBuf = new byte[1];
		
		RandomAccessFile accessFile = null;
		DatagramPacket dpk = null;
		DatagramSocket dsk = null;
		int readSize = -1;
		try {
			accessFile = new RandomAccessFile(SEND_FILE_PATH,"r");
			dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("localhost"), UDPUtils.PORT + 1));
			dsk = new DatagramSocket(UDPUtils.PORT, InetAddress.getByName("localhost"));
			int sendCount = 0;
			while((readSize = accessFile.read(buf,0,buf.length)) != -1){
				dpk.setData(buf, 0, readSize);
				dsk.send(dpk);
				// wait server response 
				{
					while(true){
						dpk.setData(receiveBuf, 0, receiveBuf.length);
						dsk.receive(dpk);
						
						// confirm server receive
						if(!UDPUtils.isEqualsByteArray(UDPUtils.successData,receiveBuf,dpk.getLength())){
							System.out.println("resend ...");
							dpk.setData(buf, 0, readSize);
							dsk.send(dpk);
						}else
							break;
					}
				}
				
				System.out.println("send count of "+(++sendCount)+"!");
			}
			// send exit wait server response
			while(true){
				System.out.println("client send exit message ....");
				dpk.setData(UDPUtils.exitData,0,UDPUtils.exitData.length);
				dsk.send(dpk);

				dpk.setData(receiveBuf,0,receiveBuf.length);
				dsk.receive(dpk);
				// byte[] receiveData = dpk.getData();
				if(!UDPUtils.isEqualsByteArray(UDPUtils.exitData, receiveBuf, dpk.getLength())){
					System.out.println("client Resend exit message ....");
					dsk.send(dpk);
				}else
					break;
			}
		}catch (Exception e) {
			e.printStackTrace();
		} finally{
			try {
				if(accessFile != null)
					accessFile.close();
				if(dsk != null)
					dsk.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		
		long endTime = System.currentTimeMillis();
		System.out.println("time:"+(endTime - startTime));
	}
}

3.UDPUtils.java

简单UDP工具类

package com.bill.udp.util;

/**
 * UDP transfer Utils  
 * @author Bill QQ:593890231
 * @since v1.0 2014/09/21
 */
public class UDPUtils {
	private UDPUtils(){}
	
	/** transfer file byte buffer **/
	public static final int BUFFER_SIZE = 50 * 1024;
	
	/** controller port  **/
	public static final int PORT = 50000;
	
	/** mark transfer success **/
	public static final byte[] successData = "success data mark".getBytes();
	
	/** mark transfer exit **/
	public static final byte[] exitData = "exit data mark".getBytes(); 
	
	public static void main(String[] args) {
		byte[] b = new byte[]{1};
		System.out.println(isEqualsByteArray(successData,b));
	}
	
	/**
	 * compare byteArray equest successData
	 * @param compareBuf 
	 * @param buf
	 * @return
	 */
	public static boolean isEqualsByteArray(byte[] compareBuf,byte[] buf){
		if (buf == null || buf.length == 0)
			return false;
		
		boolean flag = true;
		if(buf.length == compareBuf.length){
			for (int i = 0; i < buf.length; i++) {
				if(buf[i] != compareBuf[i]){
					flag = false;
					break;
				}
			}
		}else
			return false;
		return flag;
	}
	
	/**
	 * compare byteArray equest successData
	 * @param compareBuf src
	 * @param buf target
	 * @return
	 */
	public static boolean isEqualsByteArray(byte[] compareBuf,byte[] buf,int len){
		if (buf == null || buf.length == 0 || buf.length < len || compareBuf.length < len)
			return false;
		
		boolean flag = true;
		
		int innerMinLen = Math.min(compareBuf.length, len);
		//if(buf.length == compareBuf.length){
			for (int i = 0; i < innerMinLen; i++) {  
				if(buf[i] != compareBuf[i]){
					flag = false;
					break;
				}
			}
		//}else 
		//	return false;
		return flag;
	}
}

 按照自己的思路,UDP丢包比较严重,开始自己实现的时候没有注意request/response的问题.也就是每次传完一个数据包双方进行握手,表示传输成功.丢包太严重.

于是后面设计了个简单的校验,client发送之后,等待server响应成功,client继续传递下一部分数据包.直至最后整个文件传输完成.进行最后一次握手,通讯结束.

由于是自己写的一个小测试,代码比较简单,没有考虑到相关线程,性能问题. 不过项目中估计要复杂些了.  希望各位小伙伴能给点意见,一起交流学习..  微笑

单机测试,传输1.3G的的mkv视频,与原文件大小一致,视频能正常播放,没有损坏. 

这里是喜欢技术,喜欢学习,喜欢交友的 Bill  ....  

版权声明:本文为博主原创文章,未经博主允许不得转载。