一、什么是UDP,它的缺点是什么?
UDP:用户数据报协议[无连接的协议]
缺点:不能保证数据的安全与可靠。
优点:消耗小,效率高
二、建立基于UDP的网络通讯程序需要使用的类和常用方法
基于UDP的网络通讯程序是不区分客户端和服务器。
java.net.DatagramPacket---该类表示数据报包。【打包被发送的数据/接收发来的数据】
构造方法:
DatagramPacket(byte[] buf, int length)
构造一个 DatagramPacket用于接收长度的数据包length。【接收发来的数据的数据包】
DatagramPacket(byte[] buf, int length, InetAddress address, int port)
构造用于发送长度的分组的数据报包 length指定主机上到指定的端口号。
实例方法:
byte[] getData() 返回数据缓冲区。
int getLength() 返回要发送的数据的长度或接收到的数据的长度。
InetAddress getAddress() 返回该数据报发送或接收数据报的计算机的IP地址。
int getPort() 返回发送数据报的远程主机上的端口号,或从中接收数据报的端口号。
UDP协议的通信程序创建步骤:
发送方步骤:
1.将需要发送的数据通过
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造方法打包好
2.通过DatagramSocket()的构造方法创建DatagramSocket对象。
3.DatagramSocket对象的send方法将打包好的数据报包,发送。
4.关闭DatagramSocket。
接收方步骤
1.通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。
2.通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。
3.通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。
4.解析数据报包
5.关闭DatagramSocket
实例1:客户端向服务器发送数据,服务器接收客户端发送来的数据
发送端package com.wangxing.test1; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPsend { public static void main(String[] args) throws Exception{ BufferedReader bufferedReader=null; int serverPort=3000; InetAddress address=null; byte data[]=null; //将需要发送的数据通过DatagramPacket对象的构造方法 DatagramPacket(byte[] buf, int length, InetAddress address, int port) DatagramPacket sendPackset=null; //通过DatagramSocket()的构造方法得到DatagramPacket对象 DatagramSocket sendSocket=null; //从键盘得到发送的数据 bufferedReader=new BufferedReader(new InputStreamReader(System.in)); System.out.print("请输入要发送的内容:"); data=bufferedReader.readLine().getBytes(); address=address.getLocalHost(); sendPackset=new DatagramPacket(data,data.length,address,serverPort); sendSocket=new DatagramSocket(); //3.DatagramSocket对象的send方法将打包好的数据报包,发送。 sendSocket.send(sendPackset); //4.关闭DatagramSocket。 sendSocket.close(); } }
接收端:
实例2:客户端向服务器持续发送数据,服务器持续接收客户端发送来的数据package com.wangxing.test1; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPreceive { public static void main(String[] args) throws Exception{ DatagramSocket receiveScoket=null; DatagramPacket receivepacket=null; int receivePort=3000; int len=0; byte data[]=new byte[1024]; InetAddress localHost=null; int port; String info=null; //1.通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 receiveScoket=new DatagramSocket(receivePort); System.out.println("接受端已经开启-------------------"); //2.通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。 receivepacket=new DatagramPacket(data,data.length); //3.通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。 receiveScoket.receive(receivepacket); //4.解析数据报包 //得到数据报中解析的数据 info=new String(receivepacket.getData()); //得到数据报中解析的数据发送方的主机IP localHost=receivepacket.getAddress(); //得到数据报中解析的数据发送方的发送数据程序的端口 port=receivepacket.getPort(); System.out.println("从"+localHost+":"+port+"上接受到的数据:"+info); //5.关闭DatagramSocket receiveScoket.close(); } }
发送端接收端package com.wangxing.test2; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPsend { public static void main(String[] args) throws Exception{ BufferedReader bufferedReader=null; int serverPort=3000; InetAddress address=null; //得到数据字符 String datastr=null; byte data[]=null; //将需要发送的数据通过DatagramPacket对象的构造方法 DatagramPacket(byte[] buf, int length, InetAddress address, int port) DatagramPacket sendPackset=null; //通过DatagramSocket()的构造方法得到DatagramPacket对象 DatagramSocket sendSocket=null; //从键盘得到发送的数据 bufferedReader=new BufferedReader(new InputStreamReader(System.in)); address=address.getLocalHost(); sendSocket=new DatagramSocket(); //判断持续执行的变量 boolean flag=true; while(flag){ System.out.print("请输入要发送的内容:"); datastr=bufferedReader.readLine(); data=datastr.getBytes(); sendPackset=new DatagramPacket(data,data.length,address,serverPort); //3.DatagramSocket对象的send方法将打包好的数据报包,发送。 sendSocket.send(sendPackset); if(datastr.equals("exit")){ flag=false; } } //4.关闭DatagramSocket。 sendSocket.close(); } }
实例3:创建发送端和客户端双向传输数据package com.wangxing.test2; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPreceive { public static void main(String[] args) throws Exception{ DatagramSocket receiveScoket=null; DatagramPacket receivepacket=null; int receivePort=3000; int len=0; byte data[]=new byte[1024]; InetAddress localHost=null; int port; String info=null; //判断持续执行的变量 boolean flag=true; //1.通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 receiveScoket=new DatagramSocket(receivePort); System.out.println("接收端已经开启-------------------"); //2.通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。 receivepacket=new DatagramPacket(data,data.length); while(flag){ //3.通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。 receiveScoket.receive(receivepacket); //4.解析数据报包 //得到数据报中解析的数据 info=new String(receivepacket.getData(),0,receivepacket.getLength()); //得到数据报中解析的数据发送方的主机IP localHost=receivepacket.getAddress(); //得到数据报中解析的数据发送方的发送数据程序的端口 port=receivepacket.getPort(); System.out.println("从"+localHost+":"+port+"上接受到的数据:"+info); if(info.equals("exit")){ flag=false; } } //5.关闭DatagramSocket receiveScoket.close(); } }
package com.wangxing.test3; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPsend { public static void main(String[] args) throws Exception{ BufferedReader bufferedReader=null; int serverPort=3000; InetAddress address=null; //得到数据字符 String datastr=null; byte data[]=null; //将需要发送的数据通过DatagramPacket对象的构造方法 DatagramPacket(byte[] buf, int length, InetAddress address, int port) DatagramPacket sendPackset=null; DatagramPacket sendPackset2=null; //通过DatagramSocket()的构造方法得到DatagramPacket对象 DatagramSocket sendSocket=null; //通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 DatagramSocket sendSocket2=null; //创建接收发送方返回的端口号 int receiveport=3001; //通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。 DatagramPacket senPack=null; //创建即将保存得到发送反返回数据的数组 byte receiveData[]=new byte[1024]; //创建返回数据字节数组 byte reData[]=new byte[1024]; //创建保存返回字节数组数据的字符串 String receiveInfo=null; //从键盘得到发送的数据 bufferedReader=new BufferedReader(new InputStreamReader(System.in)); address=InetAddress.getLocalHost(); sendSocket=new DatagramSocket(); //接收返回的数据 sendSocket2=new DatagramSocket(receiveport); //创建接收返回数据的心数据报包 sendPackset2=new DatagramPacket(receiveData,receiveData.length); //判断持续执行的变量 boolean flag=true; while(flag){ System.out.print("请输入要发送的内容:"); datastr=bufferedReader.readLine(); data=datastr.getBytes(); sendPackset=new DatagramPacket(data,data.length,address,serverPort); //3.DatagramSocket对象的send方法将打包好的数据报包,发送。 sendSocket.send(sendPackset); //使用DatagramSocket对象的实例方法receive()接收数据报包 sendSocket2.receive(sendPackset2); receiveData=sendPackset2.getData(); receiveInfo=new String(receiveData,0,sendPackset2.getLength()); System.out.println(receiveInfo); if(datastr.equals("exit")){ flag=false; } } //4.关闭DatagramSocket。 sendSocket.close(); sendSocket2.close(); } }
实例4:多个客户端端给一个服务端package com.wangxing.test3; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPreceive { public static void main(String[] args) throws Exception{ DatagramSocket receiveScoket=null; DatagramSocket receiveScoket2=null; DatagramPacket receivepacket2=null; DatagramPacket receivepacket=null; int receivePort=3000; int len=0; byte arr[]=new byte[1024]; InetAddress localHost=null; //定义发送数据段程序的端口 int port; //保存返回给发送端的端口 int sendPort=3001; //创建得到数据的字节数组 byte data[]=null; //创建的得到数据字符串 String info=null; //得到返回数组的IP InetAddress receiveAddress=InetAddress.getLocalHost(); //判断持续执行的变量 boolean flag=true; //1.通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 receiveScoket=new DatagramSocket(receivePort); //通过通过DatagramPacket(byte[] buf, int length) System.out.println("接收端已经开启-------------------"); //2.通过DatagramPacket(byte[] buf, int length, InetAddress address, int port) receivepacket=new DatagramPacket(arr,arr.length); while(flag){ //3.通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。 receiveScoket.receive(receivepacket); //4.解析数据报包 //得到数据报中解析的数据 info=new String(receivepacket.getData(),0,receivepacket.getLength()); //得到数据报中解析的数据发送方的主机IP localHost=receivepacket.getAddress(); //得到数据报中解析的数据发送方的发送数据程序的端口 port=receivepacket.getPort(); System.out.println("从"+localHost+":"+port+"上接受到的数据:"+info); //得到数据后返回给发送方结果 String xinxi="接收方返回---"; data=(xinxi+info).getBytes(); receivepacket2=new DatagramPacket(data,data.length,receiveAddress,sendPort); receiveScoket2=new DatagramSocket(); receiveScoket2.send(receivepacket2); if(info.equals("exit")){ flag=false; } } //5.关闭DatagramSocket receiveScoket.close(); receiveScoket2.close(); } }
客户端(主要得到发客户端的端口,因为客户端本身使用了自己的端口了,接收服务端返回值时需要打开自己接收数据的端口所以讲这个端口+1就可以了,和服务端向客户端的接收地址的端口一致就可以了)服务端(服务端需要和客户端的调用的接收数据的端口一致)package com.wangxing.test4; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPsend { public static void main(String[] args) throws Exception{ BufferedReader bufferedReader=null; int serverPort=3000; InetAddress address=null; //得到数据字符 String datastr=null; byte data[]=null; //将需要发送的数据通过DatagramPacket对象的构造方法 DatagramPacket(byte[] buf, int length, InetAddress address, int port) DatagramPacket sendPackset=null; DatagramPacket sendPackset2=null; //通过DatagramSocket()的构造方法得到DatagramPacket对象 DatagramSocket sendSocket=null; //通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 DatagramSocket sendSocket2=null; //通过DatagramPacket(byte[] buf, int length) 创建一个空的数据报包。 DatagramPacket senPack=null; //创建即将保存得到发送反返回数据的数组 byte receiveData[]=new byte[1024]; //创建返回数据字节数组 byte reData[]=new byte[1024]; //创建保存返回字节数组数据的字符串 String receiveInfo=null; //从键盘得到发送的数据 bufferedReader=new BufferedReader(new InputStreamReader(System.in)); address=InetAddress.getLocalHost(); sendSocket=new DatagramSocket(); int cilentPort=sendSocket.getLocalPort(); System.out.print(cilentPort); //接收返回的数据打开发送方的端口 sendSocket2=new DatagramSocket(cilentPort+1); //创建接收返回数据的心数据报包 sendPackset2=new DatagramPacket(receiveData,receiveData.length); //判断持续执行的变量 boolean flag=true; while(flag){ System.out.print("请输入要发送的内容:"); datastr=bufferedReader.readLine(); data=datastr.getBytes(); sendPackset=new DatagramPacket(data,data.length,address,serverPort); //3.DatagramSocket对象的send方法将打包好的数据报包,发送。 sendSocket.send(sendPackset); //使用DatagramSocket对象的实例方法receive()接收数据报包 sendSocket2.receive(sendPackset2); receiveData=sendPackset2.getData(); receiveInfo=new String(receiveData,0,sendPackset2.getLength()); System.out.println(receiveInfo); if(datastr.equals("exit")){ flag=false; } } //4.关闭DatagramSocket。 sendSocket.close(); sendSocket2.close(); } }
创建服务端的线程package com.wangxing.test4; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class UDPreceive { public static void main(String[] args) throws Exception{ DatagramSocket receiveScoket=null; DatagramPacket receivepacket=null; int receivePort=3000; InetAddress receiveAddress =InetAddress.getLocalHost() ; int len=0; byte arr[]=new byte[1024]; //1.通过DatagramSocket(int port)创建接收数据的DatagramSocket对象。 receiveScoket=new DatagramSocket(receivePort); //通过通过DatagramPacket(byte[] buf, int length) System.out.println("接收端已经开启-------------------"); //2.通过DatagramPacket(byte[] buf, int length, InetAddress address, int port) receivepacket=new DatagramPacket(arr,arr.length); ReceiveThread receiveThread=new ReceiveThread(receiveScoket, receivepacket, receiveAddress); Thread thread=new Thread(receiveThread); thread.start(); } }
package com.wangxing.test4; import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public class ReceiveThread implements Runnable { private DatagramSocket receiveScoket = null; private DatagramSocket receiveScoket2 = null; private DatagramPacket receivepacket2 = null; private DatagramPacket receivepacket = null; private InetAddress receiveAddress = null; private InetAddress localHost = null; // 定义发送数据段程序的端口 private int port; // 创建得到数据的字节数组 private byte data[] = null; // 创建的得到数据字符串 private String info = null; // 判断持续执行的变量 private boolean flag = true; public ReceiveThread(DatagramSocket receiveScoket, DatagramPacket receivepacket, InetAddress receiveAddress) { this.receiveScoket = receiveScoket; this.receivepacket = receivepacket; this.receiveAddress = receiveAddress; } @Override public void run() { try { while (flag) { // 3.通过调用接收数据的DatagramSocket对象的receive方法接收数据报包到空的数据报包。 receiveScoket.receive(receivepacket); // 4.解析数据报包 // 得到数据报中解析的数据 info = new String(receivepacket.getData(), 0, receivepacket.getLength()); // 得到数据报中解析的数据发送方的主机IP localHost = receivepacket.getAddress(); // 得到数据报中解析的数据发送方的发送数据程序的端口 port = receivepacket.getPort(); System.out.println("从" + localHost + ":" + port + "上接受到的数据:" + info); // 得到数据后返回给发送方结果 String xinxi = "接收方返回---"; data = (xinxi + info).getBytes(); receivepacket2 = new DatagramPacket(data, data.length, receiveAddress, port+1); receiveScoket2 = new DatagramSocket(); receiveScoket2.send(receivepacket2); if (info.equals("exit")) { flag = false; } } //5.关闭DatagramSocket receiveScoket.close(); receiveScoket2.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }