现在的位置: 首页 > 综合 > 正文

Java利用TCP协议发送文件(二)–数据包设计

2018年04月13日 ⁄ 综合 ⁄ 共 5014字 ⁄ 字号 评论关闭

    虽然TCP协议是可靠传输协议,但是,在服务器端,接受缓冲总是有限的,因此,如果不将数据进行分包发送,在传送的过程中,就无法判断接受到的数据是上一次还没发完的部分,还是新发送的数据。同时,为了更方便地对接收到的数据根据不同的类型进行设计,需要将发送的数据的类型添加到要发送的数据中去,根据上面的两个方面的原因,需要在数据分包发送,并且加入包头。

    数据包的设计如下:



    由于在Java中,使用TCP Socket发送的时候,我使用的是BufferedOutputStream作为输出缓冲的,因此,发送的部分只能是byte数组,因此,必须将数据包中的int类型的变量转化为byte数组存储和发送,这个可以参考我前面的博客Java
将byte[] 与int类型互相转换
 ,为了方便起见,我把数据包封装成一个单独的类,并且在类中定义了用于将数据包的头部和数据内容打包成一个byte数据的方法,同时,也定义了一个将byte数组解包的函数。有了这些函数,就可以一个数据包一个数据包地接收数据了。

     具体的代码如下:
package edu.pkusz.sheng;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;



/**
 * 
 */

/**
 * @author sheng
 *
 */
public class DataPackage
{
	//
	protected boolean IsReceiver = false;
	
	// The file header
	protected PackageType Type = null;
	protected int NumberOfPackages = 0;
	protected int IndexOfPackages  = 0;
	protected int SizeOfData       = 0;
	
	// The content of the data
	protected byte[] Content = null;
	
	
	public DataPackage(boolean IsReceiver)
	{
		this.IsReceiver = IsReceiver;
	}
	
	
	public PackageType GetType()
	{
		if (IsReceiver == true)
		{
			return this.Type;
		}
		
		return PackageType.NULLTYPE;
	}
	
	
	public int GetNumberOfPackages()
	{
		if (IsReceiver == true)
		{
			return this.NumberOfPackages;
		}
		
		return 0;
	}
	
	
	public int GetIndexOfPackages()
	{
		if (IsReceiver == true)
		{
			return this.IndexOfPackages;
		}
		
		return 0;
	}
	
	
	public int GetSizeOfData()
	{
		if (IsReceiver == true)
		{
			return this.SizeOfData;
		}
		
		return 0;
	}
	
	
	public byte[] GetContent()
	{
		if (IsReceiver == true)
		{
			return this.Content;
		}
		
		return null;
	}
	
	
	
	public boolean SetType(PackageType Type)
	{
		if (IsReceiver == false)
		{
			this.Type = Type;
			return true;
		}
		
		return false;
	}
	
	
	public boolean SetNumberOfPackages(int NumberOfPackages)
	{
		if (IsReceiver == false)
		{
			this.NumberOfPackages = NumberOfPackages;
			return true;
		}
		
		return false;
	}
	
	
	public boolean SetIndexOfPackages(int IndexOfPackages)
	{
		if (IsReceiver == false)
		{
			this.IndexOfPackages = IndexOfPackages;
			return true;
		}
		
		return false;
	}
	
	
	public boolean SetSizeOfData(int SizeOfData)
	{
		if (IsReceiver == false)
		{
			this.SizeOfData = SizeOfData;
			return true;
		}
		
		return false;
	}
	
	
	
	
	public boolean SetContent(byte[] Content)
	{
		if (IsReceiver == false)
		{
			this.Content = Content;
			return true;
		}
		
		return false;
	}
	
	//
	protected  byte[] Packing()
	{
		byte[] packageData = new byte[BufferSize.PACKAGEHEADERSIZE + SizeOfData];
		
		byte [] Tmp;
		int Offset = 0;
		
		// The file type
		Tmp = Converter.ConvertIntToByteArray(Type.ordinal());
		System.arraycopy(Tmp, 0, packageData, Offset, BufferSize.INTSIZE);
		Offset += BufferSize.INTSIZE;
		
		// The NumberOfPackages
		Tmp = Converter.ConvertIntToByteArray(NumberOfPackages);
		System.arraycopy(Tmp, 0, packageData, Offset, BufferSize.INTSIZE);
		Offset += BufferSize.INTSIZE;
		
		// The IndexOfPackages
		Tmp = Converter.ConvertIntToByteArray(IndexOfPackages);
		System.arraycopy(Tmp, 0, packageData, Offset, BufferSize.INTSIZE);
		Offset += BufferSize.INTSIZE;
		
		
		// The DataSize
		Tmp = Converter.ConvertIntToByteArray(SizeOfData);
		System.arraycopy(Tmp, 0, packageData, Offset, BufferSize.INTSIZE);
		Offset += BufferSize.INTSIZE;
		
		
		// Content
		System.arraycopy(Content, 0, packageData, Offset, SizeOfData);
		
		
		return packageData;
	}
	
	
	
	protected boolean Unpacking(byte[] Data, int Lenth)
	{
		byte [] Tmp = new byte[BufferSize.INTSIZE];
		int Offset = 0;
		
		// Package Type
		System.arraycopy(Data, Offset, Tmp, 0, BufferSize.INTSIZE);
		this.Type = PackageType.values()[Converter.ConvertByteArrayToInt(Tmp)];
		Offset += BufferSize.INTSIZE;
		
		// The NumberOfPackages
		System.arraycopy(Data, Offset, Tmp, 0, BufferSize.INTSIZE);
		this.NumberOfPackages = Converter.ConvertByteArrayToInt(Tmp);
		Offset += BufferSize.INTSIZE;
		
		// The Index of Packages
		System.arraycopy(Data, Offset, Tmp, 0, BufferSize.INTSIZE);
		this.IndexOfPackages = Converter.ConvertByteArrayToInt(Tmp);
		Offset += BufferSize.INTSIZE;
		
		// The SizeOfData
		System.arraycopy(Data, Offset, Tmp, 0, BufferSize.INTSIZE);
		this.SizeOfData = Converter.ConvertByteArrayToInt(Tmp);
		Offset += BufferSize.INTSIZE;
			
		
//		System.out.println("The number of package is " + this.NumberOfPackages);
//		System.out.println("The index of package is " + this.IndexOfPackages);
//		System.out.println("The size of data is " + this.SizeOfData);
		
		// The content
		this.Content = new byte[this.SizeOfData];
		System.arraycopy(Data, Offset, this.Content, 0, SizeOfData);
		
		return true;
	}
	
	
	
	public boolean Send(BufferedOutputStream OutputStream) 
	{
		// TODO Auto-generated method stub
		
		if (IsReceiver == false)
		{
			int PackageSize = BufferSize.PACKAGEHEADERSIZE + SizeOfData;
			byte [] TmpData = Packing();
			
			byte [] SendData = null;
			
			// 当数据包的大小小于缓冲区的大小时,填充数据包
			if (BufferSize.BUFFERSIZE > PackageSize)
			{
				SendData = new byte[BufferSize.BUFFERSIZE];
				System.arraycopy(TmpData, 0, SendData, 0, PackageSize);
			}
			else  //当数据包的大小等于缓冲区的时候,不做其他处理
			{
				SendData = TmpData;
			}
			
			try {
				OutputStream.write(SendData, 0, BufferSize.BUFFERSIZE);
				OutputStream.flush();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}	
			return true;
		}
		else
		{
			return false;
		}
	}
	
	
	
	public int Receive(BufferedInputStream InputStream) 
	{
		// TODO Auto-generated method stub
		
		if (IsReceiver == true)
		{
			byte[] Data = new byte[BufferSize.BUFFERSIZE];
			int Len = 0;
			
			try 
			{
				Len = InputStream.read(Data);
			} catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
//			System.out.println("The len of data is " + Len);
			if (Unpacking(Data, Len))
			{
				return Len;
			}
						
			return 0;
		}
		else
		{
			return 0;
		}
	}
	
	
	public boolean SaveContent(BufferedOutputStream OutputFile) 
	{
		if (IsReceiver == true)
		{
		// TODO Auto-generated method stub
			try 
			{
				OutputFile.write(Content, 0, this.SizeOfData);
				OutputFile.flush();
			} 
			catch (IOException e) 
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		return true;
		}
		else 
		{
			return false;
		}
		
	}
	
}

抱歉!评论已关闭.