扣扣技术交流群:460189483
参考链接如下,写的非常非常好,我只是把他们写的优秀的搬过来做笔记,防止以后忘记,本博客所有内容均经过代码验证
https://blog.csdn.net/ITermeng/article/details/73482669?locationNum=9&fps=1
https://blog.csdn.net/weixin_37716758/article/details/81359092
1. 安卓UDP发送步骤
1. 构造DatagramSocket对象
2. 根据发送IP 来创建InetAddress对象
3. 根据InetAddress对象、发送端口号、发送数据 来创建发送的DatagramPacket数据包对象
4. 调用DatagramSocket对象的send(datagramPacket) 方法,发送UDP报文
5. 调用DatagramSocket对象的close() 关闭套接字连接
2. 安卓UDP接收步骤
1. 需要根据接收端口号 构造DatagramSocket对象
2. 创建发送的DatagramPacket数据包对象
3. 调用DatagramSocket对象的receive(datagramPacket)
方法,接收UDP报文
一 . 基础知识解释
首先学习了解一下UDP、TCP是什么东西,基础知识的链接如下,非常全了,不再赘述
https://blog.csdn.net/itermeng/article/details/72970099
通过上面的UDP发送、接收步骤可以看出来,DatagramSocket、InetAddress、DatagramPacket这3个对象很关键,下面给出三个对象的构造函数及方法,补充一下基础,如下:
1.1 DatagramSocket学习
(1)定义概念
此类表示用来发送和接收数据报包的套接字。
数据报套接字是包投递服务的发送或接收点。每个在数据报套接字上发送或接收的包都是单独编址和路由的。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。
在 DatagramSocket 上总是启用 UDP 广播发送。为了接收广播包,应该将 DatagramSocket 绑定到通配符地址。在某些实现中,将 DatagramSocket 绑定到一个更加具体的地址时广播包也可以被接收。
(2)构造函数总结
构造函数名称 | 含义 |
DatagramSocket() | 构造数据报套接字并将其绑定到本地主机上任何可用的端口。 |
DatagramSocket(int port) | 创建数据报套接字并将其绑定到本地主机上的指定端口。 |
DatagramSocket(int port, InetAddress laddr) | 创建数据报套接字,将其绑定到指定的本地地址。 |
(3)重要方法摘要
方法名称 | 含义 |
void close() | 关闭此数据报套接字。 |
void connect(InetAddress address, int port) | 将套接字连接到此套接字的远程地址 |
boolean isClosed() | 返回是否关闭了套接字。 |
void receive(DatagramPacket p) | 从此套接字接收数据报包。 |
void send(DatagramPacket p) | 从此套接字发送数据报包。 |
DatagramSocket(int port, InetAddress laddr) | 创建数据报套接字,将其绑定到指定的本地地址。 |
1.2 InetAddress学习
(1) 定义概念
此类表示互联网协议 (IP) 地址。
IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的。InetAddress 的实例包含 IP 地址,还可能包含相应的主机名(取决于它是否用主机名构造或者是否已执行反向主机名解析)。
(2)创建方法
注意,创建此类事通过类方法而获取,并非构造方法。
方法名称 | 含义 |
static InetAddress getByAddress(byte[] addr) | 在给定原始 IP 地址的情况下,返回 InetAddress 对象。 |
static InetAddress getByAddress(String host, byte[] addr) | 根据提供的主机名和 IP 地址创建 InetAddress。 |
static InetAddress getByName(String host) | 在给定主机名的情况下确定主机的 IP 地址。 |
表示数据报包。
1.3 DatagramPacket学习
(1)定义概念
此类表示数据包。
数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。
(2)构造方法
构造函数名称 | 含义 |
DatagramPacket(byte[] buf, int length) | 用来接收长度为 length 的数据包 |
DatagramPacket(byte[] buf, int length, InetAddress address, int port) | 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号 |
二. 发送、接收UDP报文步骤讲解
在此程序中,将UDP报文的发送、接收操作分别写入到两个线程中,根据具体需求进行调用。
2.1. 数据报发送 解析
以下步骤都在发送线程内,需要注意的是发送UDP报文逻辑单一,顺序执行完毕线程即可结束,不涉及到后台等待的需求,所以执行完后即可关闭套接字连接。
发送步骤
- 构造DatagramSocket对象
- 根据发送IP 来创建InetAddress对象
- 根据InetAddress对象、发送端口号、发送数据 来创建发送的DatagramPacket数据包对象
- 调用DatagramSocket对象的send(datagramPacket) 方法,发送UDP报文
- 调用DatagramSocket对象的close() 关闭套接字连接
对应以上步骤,代码展示(仅为部分重要代码):
Byte[] buf="hello android! ".getBytes();
DatagramSocket sendSocket = new DatagramSocket();
InetAddress serverAddr = InetAddress.getByName(SEND_IP);
DatagramPacket outPacket = new DatagramPacket(buf, buf.length,serverAddr, SEND_PORT);
sendSocket.send(outPacket);
sendSocket.close();
2.2 数据报接收 解析
以下步骤都在接收线程内,同发送线程大致相同,但需要注意这两者本质的区别:发送线程里的逻辑执行一遍即可结束,但是接收线程需要在后台待定等待接收UDP报文,不可执行一遍就结束!相当于在一个界面中,可多次创建发送线程用来发送报文,但是接收线程只需在界面初始化时创建,从而一直监听报文接收(若重新进入界面,逻辑如上)。
所以,在接收线程内部需要用到循环,在循环内部调用套接字对象的receive() 方法来接收UDP报文。注意套接字对象的连接关闭,发送线程中单一的逻辑,执行完发送过程即可关闭连接,但是在接收线程中使用了循环,所以需要用一个全局标识量来控制循环,若界面退出或销毁则将标示值置为false,这样接收线程即可结束,再关闭套接字连接。
接收步骤
- 需要根据接收端口号 构造DatagramSocket对象
- 创建发送的DatagramPacket数据包对象
- 调用DatagramSocket对象的receive(datagramPacket) 方法,接收UDP报文
对应以上步骤,代码展示(仅为部分重要代码):
DatagramSocket receiveSocket = new DatagramSocket(RECEIVE_PORT);
while(listenStatus){
byte[] inBuf= new byte[1024];
DatagramPacket inPacket=new DatagramPacket(inBuf,inBuf.length);
receiveSocket.receive(inPacket);
if(!inPacket.getAddress().equals(serverAddr)){
throw new IOException("未知名的报文");
}
receiveInfo = inPacket.getData();
receiveHandler.sendEmptyMessage(1);
}