UDP协议是非连接协议,不与目标地址建立连接,简单说就是只负责发送给目标地址数据,不等待目标返回结果。每次发送只能是少量数据,不过可以少量多次发送,发送几M的图片还是没问题的。
以下是我发送数据和接收数据的相关代码,以供参考。
/***
*
* @param licensePlate 业务数据
* @param platPicUrls 业务图片地址
* @param pudipconfig 目标地址ip、端口号,服务地址的端口号(用于监听是否有数据进入)
* @throws Exception
*/
public void sendAllUDP(LicensePlate licensePlate, List platPicUrls,Pudipconfig pudipconfig) throws Exception {
//初始化用于发送数据
byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
//初始化用户接收数据
byte[] receiveBuf = new byte[100];
//定义照片
RandomAccessFile accessFile = null;
//定义服务端
DatagramSocket dsk = null;
//定义数据包
DatagramPacket dpk;
//定义读取大小
int readSize;
try {
//初始化服务端 参数为端口号,作用在于监听该端口号是否有数据交互
dsk = new DatagramSocket(Integer.parseInt(pudipconfig.getExt1()));
//初始化数据包 参数为:byte类型存放数据,数据大小,目标地址,目标端口
dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName(pudipconfig.getIpaddress()), Integer.parseInt(pudipconfig.getIpport())));
//将需要发送的业务数据转成byte类型并放入数据包
dpk.setData(licensePlate.getLicenseplatenumber().getBytes("UTF-8"),0,licensePlate.getLicenseplatenumber().getBytes().length);
//发送数据
dsk.send(dpk);
//为保证数据准确性,在每次发送数据后等待目标地址反向调用发送端的ip+端口,并用receiveBuf存下返回的数据是否成功
//该方式只适用于单对单传输
dpk.setData(receiveBuf, 0, receiveBuf.length);
//等待目标地址返回数据
dsk.receive(dpk);
// 验证服务端返回成功 成功则进入下一步发送附件(图片)数据
if(UDPUtils.isEqualsByteArray("success_title".getBytes(),receiveBuf,dpk.getLength())){
//记录发送附件数次数
int sendCount = 0;
//以下为发送附件(图片)部分
//获取保存文件夹路径
String t=Thread.currentThread().getContextClassLoader().getResource("").getPath();
int num=t.indexOf("jeesite/WEB-INF");
//遍历发送多个附件(图片)
for (String platPicUrl : platPicUrls) {
sendCount++;
// accessFile = new RandomAccessFile(platPicUrl,"r");
//获取车牌照文件
accessFile = new RandomAccessFile(t.substring(1,num-1)+java.net.URLDecoder.decode(platPicUrl, "UTF-8"),"r");
//循环读取车牌照,目的是附件需要多次发送才能完成,UDP协议一次只能发送最多64k的数据
while ((readSize = accessFile.read(buf,0,buf.length)) != -1){
System.out.println(Arrays.toString(buf));
//发送附件数据
dpk.setData(buf,0,readSize);
dsk.send(dpk);
//每次发送都等待目标地址返回成功标识
dpk.setData(receiveBuf, 0, receiveBuf.length);
dsk.receive(dpk);
// 验证服务端返回成功
if(!UDPUtils.isEqualsByteArray("success_pic".getBytes(),receiveBuf,"success_pic".getBytes().length))
throw new Exception("车牌照验证错误:success_pic");
}
System.out.println(sendCount);
//发送一个附件发送结束标识
dpk.setData("end_pic".getBytes("UTF-8"));
dsk.send(dpk);
//等待目标地址返回一个附件结束验证成功
dpk.setData(receiveBuf, 0, receiveBuf.length);
dsk.receive(dpk);
// 验证服务端返回成功 一张照片成功
if(!UDPUtils.isEqualsByteArray("success_end".getBytes(),receiveBuf,"success_end".getBytes().length))
throw new Exception("附件验证错误:success_end");
}
//发送验证所有数据发送完成,程序结束
dpk.setData("end_all".getBytes("UTF-8"), 0, "end_all".getBytes().length);
dsk.send(dpk);
} else {
throw new Exception("附件发送失败!");
}
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(accessFile != null)
accessFile.close();
if(dsk != null)
dsk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 作为客户端接收数据
*/
public void getUDP2(){
byte[] buf = new byte[UDPUtils.BUFFER_SIZE];
DatagramPacket dpk = null;
DatagramSocket dsk = null;
BufferedOutputStream bos = null;
try {
//初始化数据包并设定目标地址ip、端口号 作为服务端可以不需要设定目标地址,这里设定是为了给客服端做成功、失败校验,保证数据的准确性
dpk = new DatagramPacket(buf, buf.length,new InetSocketAddress(InetAddress.getByName("192.168.0.110"), 8198));
//初始化服务端并设定监听端口号
dsk = new DatagramSocket(UDPUtils.PORT2);
//用于给附件定义名称
int flag = 0;
//给定无限循环 不间断接收数据,一直保持监听状态
while (true){
System.out.println(flag);
System.out.println("wait client1 ...."+ new String(buf,0,20));
//等待接收客服端发送数据
//receive是一个阻塞型的方法,没有接收到数据包之前会一直等待。 数据实际上就是存储到了byte的自己数组中了。
dsk.receive(dpk);
//发送给客服端接收成功
dpk.setData("success_title".getBytes(), 0, "success_title".getBytes().length);
dsk.send(dpk);
/**接收附件循环*/
while (true){
flag ++;
//等待附件
dpk.setData(buf,0, buf.length);
System.out.println("wait client2 ...."+new String(buf,0,20));
dsk.receive(dpk);
int readSize = 0;
int readCount = 0;
int flushSize = 0;
if (UDPUtils.isEqualsByteArray("end_all".getBytes(), buf, "end_all".getBytes().length)){
System.out.println("server end ...");
break;
} else {
//创建文件
bos = new BufferedOutputStream(new FileOutputStream("D:/demoPic/2013_" + flag+".jpg"));
}
while((readSize = dpk.getLength()) != 0){
// validate client send exit flag
if(UDPUtils.isEqualsByteArray("end_pic".getBytes(), buf, readSize)){
System.out.println("server exit ...");
// send exit flag
dpk.setData("success_end".getBytes(), 0, "success_end".getBytes().length);
dsk.send(dpk);
break;
}
//将接收到的数据写入文件中
bos.write(buf, 0, readSize);
if(++flushSize % 1000 == 0){
flushSize = 0;
bos.flush();
}
dpk.setData("success_pic".getBytes(), 0, "success_pic".getBytes().length);
dsk.send(dpk);
dpk.setData(buf,0, buf.length);
System.out.println("receive count of "+ ( ++readCount ) +" !");
System.out.println("wait client3 ...." + new String(buf,0,20));
dsk.receive(dpk);
}
// last flush
bos.flush();
if(UDPUtils.isEqualsByteArray("end_all".getBytes(), buf, readSize)){
System.out.println("server end4 ...");
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
} finally{
try {
if(bos != null)
bos.close();
if(dsk != null)
dsk.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}