网络编程之UDP
UDP协议
UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。
由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。
但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。
DatagramPacket 类:封装UDP通信中发送或者接收的数据。
创建DatagramPacket对象时,不仅指定了封装数据的字节数组和数据的大小,还指定了数据包的目标IP地址(addr)和端口号(port)。该对象通常用于发送端,因为在发送数据时必须指定接收端的IP地址和端口号,就好像发送货物的集装箱上面必须标明接收人的地址一样。
DatagramSocket 类: 作用就类似于码头,使用这个类的实例对象就可以发送和接收DatagramPacket数据包
InetAddress 类:封装一个IP地址,并提供了一系列与IP地址相关的方法,主要有getLocalhost()返回本地主机IP地址的封装对象; getByName(String IP)根据字符串ip地址或者域名得到ip地址的封装对象InetAddress; getHostName()根据InetAddress对象获取此IP对象的主机名; getHostAddress()根据InetAddress对象获取此IP对象的IP地址,返回IP地址的字符串;
要实现UDP通信需要创建一个发送端程序和一个接收端程序,很明显,在通信时只有接收端程序先运行,才能避免因发送端发送的数据无法接收,而造成数据丢失。因此,首先需要来完成接收端程序的编写。
1 import java.io.IOException; 2 import java.net.DatagramPacket; 3 import java.net.DatagramSocket; 4 import java.net.InetAddress; 5 /** 6 * UTP数据发送端 7 * 8 */ 9 public class Send { 10 public static void main(String[] args) throws IOException { 11 //1.创建数据报包套接字DatagramSocket对象 12 DatagramSocket socket = new DatagramSocket(); 13 /* 数据报包需要接收数据,先准备数据 14 * DatagramPacket(byte[] bytes,int length,InetAddress ip,int port); 15 */ 16 //2.设置参数 17 byte[] bytes="hello,word".getBytes(); 18 int length = bytes.length; 19 //通过IP地址字符串,获取IP封装对象 20 InetAddress ip = InetAddress.getByName("127.0.0.1"); 21 int porn = 6666; 22 //3.创建数据报包DatagramPacket对象,并封装数据 23 DatagramPacket dp =new DatagramPacket(bytes,length,ip,porn); 24 //4.套接字发送数据报包 25 socket.send(dp); 26 //5.释放资源 27 socket.close(); 28 } 29 } 30
1 package udpdemo; 2 3 import java.io.IOException; 4 import java.net.DatagramPacket; 5 import java.net.DatagramSocket; 6 import java.net.InetAddress; 7 /** 8 * 9 * UDP接收端 10 * 11 */ 12 13 14 public class Receive { 15 public static void main(String[] args) throws IOException { 16 //设置接受数据的端口 17 int porn = 8888; 18 //创建接收端的DatagramSocket对象 19 DatagramSocket socket = new DatagramSocket(porn); 20 //创建接受数据的字节数组 21 byte [] receive = new byte[1024]; 22 //限制接受数据的长度 23 int length = 1024; 24 //创建接受端的数据报包对象 25 DatagramPacket dp = new DatagramPacket(receive,length); 26 //接收数据存储到数据报包dp中 27 socket.receive(dp); 28 /** 29 * 拆包获取数据 30 * geAddress()根据数据报包获取发送端的ip地址对象 31 * getHostAddress() 根据ip地址对象获取IP地址 32 * getHostName() 根据IP地址对象获取此IP的主机名 33 * 34 * getData()根据数据报包获取数据,返回值byte[]类型 35 * getLength()根据数据报包获取实际接受数据的数量 36 * 37 * 38 */ 39 //根据数据报包获取发送端的ip地址对象 40 InetAddress ipObject = dp.getAddress(); 41 // 根据ip地址对象获取IP地址 42 String ip=ipObject.getHostAddress(); 43 //根据IP地址对象获取此IP的主机名 44 String hostName=ipObject.getHostName(); 45 //获取端口 46 int receiveporn=dp.getPort(); 47 //获取接受数据的长度 48 int str=dp.getLength(); 49 //获取数据包接受的数据 50 byte[] receiveb=dp.getData(); 51 52 53 54 // 打印数据 55 System.out.println("发送端IP地址对象:"+ipObject); 56 System.out.println("发送端IP地址"+ip); 57 System.out.println("获取发送端主机名"+hostName); 58 System.out.println("获取发送端数据报包数据"+new String(receiveb,0,str)); 59 System.out.println("获取发送端端口:"+receiveporn); 60 System.out.println("获取数据长度:"+str); 61 socket.close(); 62 63 } 64 /**输出 65 * 发送端IP地址对象:www.fu.com/127.0.0.1 66 发送端IP地址127.0.0.1 67 获取发送端主机名www.fu.com 68 获取发送端数据报包数据hello,word 69 获取发送端端口:59399 70 获取数据长度:10 71 * 72 * 73 */ 74 75 }