Java基础(38)——网络编程相关知识详解及示例分析五(UDP通信技术详解及示例)
版权声明
- 本文原创作者:清风不渡
- 博客地址:https://blog.csdn.net/WXKKang
UDP通信
1、UDP通信概述
(1)通信过程描述
UDP协议是一种对等通信的实现,发送方只需要知道接收方的IP和Port,就可以直接向它发送数据,不需要事先连接。每个程序都可以作为服务器,也可以作为客户端。UDP是一种无连接的传输协议,它以数据报(DatagramPacket)作为数据传输的载体。数据报的大
小是受限制的,每个数据报的大小限定在64KB以内。数据报是一个在网络上发送的独立信息,它的到达、到达时间以及内容本身等都不能得到保证。这种传输方式是无序的,也不能确保绝对的安全可靠,但它很简单也具有较高的效率,这与通过邮局发送邮件的情形非常相似
使用UDP协议进行数据传输时,需要将要传输数据定义为数据报(DatagramPacket),在数据报中指明数据所要达到的Socket(主机地址和端口号),然后再将数据报发送出去。实例化DatagramPacket时使用参数port和没有使用参数port的区别在于,提供port的一方可以让别人主动发送消息过来,而没有参数port 的则会在发送消息时自动绑定一个本地没有使用的端口。在接收到发送方的数据(DatagramPacket) 时,不仅可以获得数据,还可以获得发送方的IP和Port,这样就可以向发送方发送数据。因此,本质上二者是对等的
通俗的来讲,UDP通信就像是我们在发短信一样,首先发短信之前不需要事先建立连接,而且数据包的大小是有限制的,就像是很早以前发短信如果太多的话就会分成两份或者三份发给接受者,并且,传输方式的无序的,这样就不能保证数据的到达或者到达时间的顺序
想想生活中的例子,时间回到好几年前人们还用着按键机的那个年代,小王暗恋上了他的同班同学小芳,但是又不敢跟人家表白,在放学的时候红着小脸蛋去要了小芳的电话号码,回到家等着爸妈睡着之后偷偷拿着爸爸的电话躲在卫生间里给小芳写了一大封情书,但是由于这封短信太大了是分成好几份发过去的,而且因为卫生间里信号不好所以有一部分是发过去了有一部分没有发过去,而且发过去的那几段被接收的时候顺序还不一样,小芳接收到之后人都傻了,这发的是什么呢?小王也是心里不知所措,她怎么不给我回复呢?到底能不能成功呀,看吧,就因为这样一段甜甜的恋爱就错过了,好可惜呀
那么,它真的没有什么好的方面吗?肯定是有的,下面我们就来谈谈UDP通信的优势吧 ~ ~
(2)UDP的特点
UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的
但是由于UDP的特性:它不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频、视频和普通数据在传送时使用UDP较多,因为它们即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。比如我们聊天用的ICQ和OICQ就是使用的UDP协议。UDP通信类似于发短消息,发送者只管把消息发出去,而对方的电话有可能处于停机、关机状态,所以对方不一定能看到发来的消息。比如:网络的音频、视频信号。UDP通信无所谓的服务器和客户端,只存在接受者和发送者
(3)DatagramSocket和DatagramPacket
UDP通信的Socket使用DatagramSocket类实现,数据报使用DatagramPacket类实现
A、DatagramSocket
DatagramSocket主要方法如下:
B、DatagramPacket
封装UDP通信数据。这个数据包中不仅包括数据,还包括目标主机地址和端口、发送主机地址和端口
在UDP协议中,接收和发送数据报的DatagramPacket的创建方式是不同的。DatagramPacket的四个参数依次表示:输出数据、数据长度、目的地址(InetAddress)、接收方端口
1、使用目标主机地址、端口作为参数,用于创建发送数据报
public DatagramPacket(byte[] buf, int length, InetAddress address, int port)
public DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port)
2、没有使用目标主机地址、端口作为参数,用于创建本地的接收数据报
public DatagramPacket(byte[] buf, int length)
public DatagramPacket(byte[] buf, int offset, int length)
DatagramPacket的主要方法如下:
(4)UDP通信的实现
无论一个UDP通信程序的功能多么齐全、程序多么复杂,其基本结构都是一样的,都包括以下四个基本步骤:
1、在接收端指定一个端口号来创建DatagramSocket,然后创建一个接收数据报( DatagramPacket),使用receive方法等待发送方的请求报文,这将阻塞服务器线程
2、在发送方创建一个DatagramSocket,使用接收方的IP和端口来创建发送数据报( DatagramPacket),使用send方法发送。现在接收方的receive方法将被唤醒,同时会将发送方的数据报内容填充到接收方的DatagramPacket中
3、接收方从发送方的数据报中获得发送方的IP和端口,使用它们构造一个发送数据报,然后发送给发送方,这样就实现了发送方和接收方的通信
4、在通信完成后,在客户端和服务端中分别关闭Socket
2、UDP编程示例
现在我们就上面所学到的知识来做一个小小的实现UDP通信的示例,我们要求,在客户端和服务端之间实现通信,客户端发送一个消息“Hello”,服务器返回一个“Welcome”,之后双方结束通信,代码如下:
接收方(服务端)代码:
package qfbd.com;
/*
原创作者:清风不渡
博客地址:https://blog.csdn.net/WXKKang
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Server {
public static void main(String[] args) throws Exception {
// 使用DatagramSocket绑定到本地端口
int port = 5000;
DatagramSocket datagramSocket = new DatagramSocket(port);
//构造接收数据报,用于接收整个数据报
byte[] buffer = new byte[64*1024];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
//接收客户端发送的消息
datagramSocket.receive(datagramPacket);
获得客户端发送过来的数据。由于使用byte[]接收数据,因此需要转换为字符数据。
String receiveMessage = new String(datagramPacket.getData(),0,datagramPacket.getLength());
System.out.println("服务端接收到的信息为:"+receiveMessage);
//从接收的数据报中获取发送方的IP、Port等信息,然后构造数据报再发送过去
byte[] sendBuffer = "Welcome".getBytes();
DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length , datagramPacket.getAddress(),datagramPacket.getPort());
//发送消息到客户端
datagramSocket.send(sendPacket);
//关闭Soket
datagramSocket.close();
}
}
发送方(客户端)代码:
package qfbd.com;
/*
原创作者:清风不渡
博客地址:https://blog.csdn.net/WXKKang
*/
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Client {
public static void main(String[] args) throws Exception {
int port = 5000;
//构造一个客户端的DatagramSocket
DatagramSocket datagramSocket = new DatagramSocket();
//使用服务端的IP、Port创建 DatagramPacket
InetAddress address = InetAddress.getLocalHost();
//构造发送给客户端的数据报
byte[] sendBuffer = "Hello".getBytes();
DatagramPacket datagramPacket = new DatagramPacket(sendBuffer, sendBuffer.length,address,port);
datagramSocket.send(datagramPacket);
/*
* 接收服务端返回的数据
* 1、创建接收数据的缓冲区
* 2、构造接收数据报的数据报对象
* 3、使用receive方法接收
*/
byte[] receiveBuffer = new byte[1024];
DatagramPacket datagramPacket2 = new DatagramPacket(receiveBuffer, receiveBuffer.length);
datagramSocket.receive(datagramPacket2);
//根据接收到的byte[]构造字符串
String receiveMessage = new String(datagramPacket2.getData(),0,datagramPacket2.getLength());
System.out.println("客户端接收到的信息为:"+receiveMessage);
//关闭Soket
datagramSocket.close();
}
}
然后首先启动服务端在启动客户端,执行结果如下:
这样我们就实现了一个简单的UDP通信示例