Android 基于UDP协议的Socket通信

一、简介

与 TCP 不同,UDP 是一个面向数据包的传输层协议,进程的每一个输出操作都正好产生一个UDP数据报,并组装成一份待发送的IP数据报。格式如下:
在这里插入图片描述
IP数据报的最大长度为 65535 字节 ,除去首字IP 的20 字节和 UDP首部8个字节,实际上,UDP 能传输的最大字节数为 65507个字节;当我们的数据超过这个长度时,则需要考虑分包的问题。
UDP 的传输是不可靠的,它只负责把数据传输出去,并不会去考虑接收端是否能接受到。在大多不需要考虑应答的应用中,我们会优先考虑 UDP

二、DatagramSocket 和 DatagramPacket

socket 的 udp 的 api 是通过 DatagramSocket 和 DatagramPacket 来实现的。
我们知道两台计算机的通信,无论是 TCP 还是 UDP ,都需要知道 IP 和 端口。
在这里插入图片描述

2.1 DatagramPacket类:数据报文

(1)定义概念

此类表示数据报包。

数据报包用来实现无连接包投递服务。每条报文仅根据该包中包含的信息从一台机器路由到另一台机器。从一台机器发送到另一台机器的多个包可能选择不同的路由,也可能按不同的顺序到达。不对包投递做出保证。

(2)构造方法

构造函数名称 含义
DatagramPacket(byte[] buf, int length) 接收构造函数, 用来接收长度为 length 的数据包
DatagramPacket(byte[] buf, int length, InetAddress address, int port) 发送构造函数,构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号

(3)主要方法

  • getAddress()返回接收或发送此数据报文的机器的 IP 地址。
  • getData()返回接收的数据或发送出的数据。
  • getLength()返回发送出的或接收到的数据的长度。
  • getPort()返回接收或发送该数据报文的远程主机端口号。

2.2 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) 创建数据报套接字,将其绑定到指定的本地地址。

2.3 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 地址。

三、发送、接收UDP报文步骤讲解

  1. 同一端如果既要发送消息又想接收消息,一定要将发送的socket和接收的socket分开。不能用一个socket既接收信息,又发送信息,这样一定会造成阻塞。
  2. 接收线程中,一定要有 while(true){ if(标志何时结束) 代码块 } 这样的方式,不然,在接收信息时,一定会造成阻塞,就是只能接收到一次信息。

3.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();

SEND_IP即是你想要发送的地址,SEND_PORT端口号则要选用闲置端口就是向8000~9000这样的端口号。

3.2 数据报接收 解析

原理
以下步骤都在接收线程内,同发送线程大致相同,但需要注意这两者本质的区别:发送线程里的逻辑执行一遍即可结束,但是接收线程需要在后台待定等待接收UDP报文,不可执行一遍就结束!相当于在一个界面中,可多次创建发送线程用来发送报文,但是接收线程只需在界面初始化时创建,从而一直监听报文接收(若重新进入界面,逻辑如上)。

所以,在接收线程内部需要用到循环,在循环内部调用套接字对

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值