UDP传输工具类serverclient.docx
《UDP传输工具类serverclient.docx》由会员分享,可在线阅读,更多相关《UDP传输工具类serverclient.docx(34页珍藏版)》请在冰豆网上搜索。
UDP传输工具类serverclient
UDP传输工具类(serverclient)
UDP不适合传输大数据,所以传输要尽量小。
UDP传输中可能会丢包,如果需要可能多次发送同一个包保证包能安全到达;接收端可以对收到的包进行CRC校验,已确定是否收到同样的包。
[java]viewplaincopy
packageorg.sl.udp.beans;
import.DatagramPacket;
/**
*处理udp请求的接口
*@authorshanl
*
*/
publicinterfaceIUdpRequestHandler{
/**
*解析请求数据包
*@paramrequestPack
*/
voidparse(DatagramPacketrequestPack);
}[java]viewplaincopy
packageorg.sl.udp.beans;
importjava.io.ByteArrayInputStream;
importjava.io.ByteArrayOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.io.PrintStream;
importjava.util.Arrays;
importjava.util.Map;
importjava.util.Properties;
importjava.util.Set;
/**
*传输包格式<br/>
*具备头校验功能。
*@authorshanl
*
*/
publicclassPacketFormat{
/**请求头,主要用于校验*/
publicstaticfinalbyte[]REQUEST_HEADER={'S','H','A','N'};
privatePropertiesprop=null;
/**
*构造一个用于发送请求的包结构
*/
publicPacketFormat(){
this.prop=newProperties();
}
/**
*解析并从请求中加载数据
*@parambuff数据包
*@paramoffset偏移量
*@paramlen长度
*@returntrue:
解析成功,false:
解析失败
*/
publicbooleanparse(byte[]buff,intoffset,intlen){
booleandone=false;
ByteArrayInputStreamdataCache=null;
ObjectInputStreamobjectIn=null;
ByteArrayInputStreampropCache=null;
try{
dataCache=newByteArrayInputStream(buff,offset,len);
byte[]d_header=newbyte[REQUEST_HEADER.length];
dataCache.read(d_header);
//校验请求头
if(!
Arrays.equals(d_header,REQUEST_HEADER)){
returnfalse;
}
objectIn=newObjectInputStream(dataCache);
//得到数据长度
shortdataLen=objectIn.readShort();
byte[]propBys=newbyte[dataLen];
objectIn.read(propBys);
propCache=newByteArrayInputStream(propBys);
//加载数据
this.prop.load(propCache);
done=true;
}catch(Exceptione){
done=false;
}finally{
try{
if(null!
=propCache)propCache.close();
}catch(Exceptionex){}
try{
if(null!
=objectIn)objectIn.close();
}catch(Exceptionex){}
try{
if(null!
=dataCache)dataCache.close();
}catch(Exceptionex){}
}
returndone;
}
/**
*设置数据
*@paramkey
*@paramvalue
*/
publicvoidsetProperty(Stringkey,Stringvalue){
this.prop.setProperty(key,value);
}
/**
*取数据
*@paramkey
*@return
*/
publicStringgetProperty(Stringkey){
returnthis.prop.getProperty(key,"");
}
/**
*返回keyset
*@return
*/
publicSet<Object>keySet(){
returnthis.prop.keySet();
}
/**
*将内容转换为byte数组
*@return
*/
publicbyte[]toBytes(){
byte[]dataCacheBys=null;
ByteArrayOutputStreamdataCache=null;
ObjectOutputStreamdataOut=null;
StringBuilderpropContent=newStringBuilder();
byte[]propBys=null;
Set<Map.Entry<Object,Object>>items=this.prop.entrySet();
for(Map.Entry<Object,Object>i:
items){
propContent.append((String)i.getKey());
propContent.append("=");
propContent.append((String)i.getValue());
propContent.append("\n");
}
propBys=propContent.toString().getBytes();
try{
dataCache=newByteArrayOutputStream();
dataCache.write(REQUEST_HEADER);
dataOut=newObjectOutputStream(dataCache);
//写入数据长度
dataOut.writeShort(propBys.length);
//写入数据
dataOut.write(propBys,0,propBys.length);
dataOut.flush();
dataCacheBys=dataCache.toByteArray();
}catch(Exceptionex){
thrownewRuntimeException(ex);
}finally{
try{
if(null!
=dataOut)dataOut.close();
}catch(Exceptionex){}
try{
if(null!
=dataCache)dataCache.close();
}catch(Exceptionex){}
}
returndataCacheBys;
}
/**
*得到请求数据
*@parambuff数据缓存,缓存大小>=128
*@paramoffset偏移量
*@return包长度=请求头长度+2+数据
*/
publicintgetBytes(byte[]buff,intoffset){
intlen=0;
//ByteArrayOutputStreampropCache=null;
ByteArrayOutputStreamdataCache=null;
ObjectOutputStreamdataOut=null;
StringBuilderpropContent=newStringBuilder();
byte[]propBys=null;
//try{
//propCache=newByteArrayOutputStream(buff.length-REQUEST_HEADER.length-2);
//this.prop.list(newPrintStream(propCache));
//propBys=propCache.toByteArray();
//}catch(Exceptionex){
//thrownewRuntimeException(ex);
//}finally{
//try{
//if(null!
=propCache)propCache.close();
//}catch(Exceptionex){}
//}
//这段代码与上面这段功能相同,但Properties的list()会写入额外的字节
Set<Map.Entry<Object,Object>>items=this.prop.entrySet();
for(Map.Entry<Object,Object>i:
items){
propContent.append((String)i.getKey());
propContent.append("=");
propContent.append((String)i.getValue());
propContent.append("\n");
}
propBys=propContent.toString().getBytes();
try{
//写入头
dataCache=newByteArrayOutputStream(buff.length);
dataCache.write(REQUEST_HEADER);
len+=REQUEST_HEADER.length;
dataOut=newObjectOutputStream(dataCache);
//写入数据长度
dataOut.writeShort(propBys.length);
len+=2;
//写入数据
dataOut.write(propBys,0,propBys.length);
dataOut.flush();
byte[]dataCacheBys=dataCache.toByteArray();
System.arraycopy(dataCacheBys,0,buff,offset,dataCacheBys.length);
len+=dataCacheBys.length;
}catch(Exceptionex){
thrownewRuntimeException(ex);
}finally{
try{
if(null!
=dataOut)dataOut.close();
}catch(Exceptionex){}
try{
if(null!
=dataCache)dataCache.close();
}catch(Exceptionex){}
}
returnlen;
}
/**
*返回crc32校验码
*@return
*/
longcrc32(){
CRC32crc32=newCRC32();
crc32.update(toBytes());
returncrc32.getValue();
}
}[java]viewplaincopy
packageorg.sl.udp.client;
importjava.io.IOException;
import.DatagramPacket;
import.DatagramSocket;
import.SocketException;
importjava.util.Random;
importjava.util.concurrent.BlockingDeque;
importjava.util.concurrent.LinkedBlockingDeque;
/**
*UDP发送请求服务
*@authorshanl
*
*/
publicclassUDPSenderService{
privateBlockingDeque<RequestObject>requestPool=null;
privatelongintervalTime=200L;
privateDatagramSocketudpSender=null;
privatebooleanshutdown=true;
privateObjectlockObj=newObject();
publicUDPSenderService(){
requestPool=newLinkedBlockingDeque<RequestObject>();
}
/**
*
*@parampoolSize请求缓冲池上限
*@paramintervalTime间隔时间
*/
publicUDPSenderService(intpoolSize,intintervalTime){
requestPool=newLinkedBlockingDeque<RequestObject>(poolSize);
this.intervalTime=intervalTime;
}
/**
*过程
*/
voidprocess(){
do{
longnow=System.currentTimeMillis();
try{
synchronized(lockObj){
lockObj.wait(intervalTime);
if(!
requestPool.isEmpty()){
send(now);
}
}
}catch(Exceptione){
e.printStackTrace();
}
}while(!
shutdown);
}
//intc=0;
privatevoidsend(longtime)throwsIOException{
RequestObjectro=null;
try{
for(inti=0;i<10;i++){
ro=requestPool.poll();
//ro=requestPool.take();
//ro=requestPool.pollFirst();
if(null!
=ro){
if(ro.getTime()<=time){
//System.out.println(c++);
udpSender.send(ro.getDataPacket());
}else{
requestPool.put(ro);
//requestPool.offerLast(ro);
}
}else{
break;
}
}
}catch(Exceptione){
e.printStackTrace();
}
}
/**
*重复多送发送一个udp请求
*@paramrequest请求包
*@paramrepeatCount重复次数
*@paraminterval重复发送请求包间隔
*/
publicvoidaddRepeatingRequest(DatagramPacketrequest,intrepeatCount,longinterval){
addImmediateRequest(request);
//timingRequest(System.currentTimeMillis(),request);
byte[]reqData=newbyte[request.getLength()-request.getOffset()];
System.arraycopy(request.getData(),request.getOffset(),reqData,request.getOffset(),request.getLength());
longnow=System.currentTimeMillis();
DatagramPacketdpClone=null;
for(longi=0,nextTime=interval;i<repeatCount;i++,nextTime+=interval){
dpClone=newDatagramPacket(reqData,request.getOffset(),request.getLength());
dpClone.setSocketAddress(request.getSocketAddress());
addTimingRequest(now+nextTime,dpClone);
}
}
/**
*添加一个定时的请求,在一个近似的时间执行发送.<br/>
*如果这个请求为过期的请求,则会在下一个时间被执行.
*@paramtime
*@paramrequest
*/
publicvoidaddTimingRequest(longtime,DatagramPacketrequest){
try{
//requestPool.offerLast(newRequestObject(time,request),300,TimeUnit.MILLISECONDS);
requestPool.put(newRequestObject(time,request));
//requestPool.offerLast(newRequestObject(time,request));
}catch(Exceptione){
e.printStackTrace();
}
synchronized(lockObj){
lockObj.notify();
}
//try{
//Thread.sleep
(1);
//}catch(InterruptedExceptione){
//}
}
/**
*立即发送一个请求
*@paramrequest
*/
publicvoidaddImmediateRequest(DatagramPacketrequest){
try{
udpSender.send(request);
}catch(Exceptionex){
ex.printStackTrace();
}
}
/**
*启动服务
*/
publicvoidstart(){
if(this.shutdown){
try{
if(null==udpSender){
udpSender=newDatagramSocket();
}
}catch(SocketExceptione1){
e1.printStackTrace();
return;
}
try{
Threadt=newThread(newProcessService(),"UDPSenderService-"+newRandom().nextInt(999));
t.start();
}catch(Exceptione){
thrownewRuntimeException(e.getMessage());
}
this.shutdown=false;
}
}
/**
*中止服务
*/
publicvoidshutdown(){
this.shutdown=true;
try{
Thread.sleep(1000*10);
}catch(Exceptionex){
}
try{
this.udpSender.disconnect();
}catch(Exceptionex){
}
try{
this.udpSender.close();
}catch(Exceptionex){