UDP局域网通信的Java实现及Android平台尝试
局域网通信已经很少被他人所提及了,我曾经还尝试过通过蓝牙构建通信网络,这次有机会尝试UDP局域网通信,在这里把一些基本过程和在Android平台上的问题记录一下。
1. UDP基础知识
1.1 什么是UDP
Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据报的方法。RFC 768 描述了 UDP。
Internet 的传输层有两个主要协议,互为补充。无连接的是 UDP,它除了给应用程序发送数据包功能并允许它们在所需的层次上架构自己的协议之外,几乎没有做什么特别的的事情。面向连接的是 TCP,该协议几乎做了所有的事情。
——《百度百科》
根据百度百科的解释,UDP是一个数据传输协议,面向无连接的数据传输方式,说明此协议丢包概率较高,不适合复杂的网络环境。UDP报文没有可靠性保证、顺序保证和流量控制字段等,可靠性较差。但是正因为UDP协议的控制选项较少,在数据传输过程中延迟小、数据传输效率高,适合对可靠性要求不高的应用程序,或者可以保障可靠性的应用程序。在局域网中,数据的到达率几乎是可以保证的,因此UDP在局域网通信中拥有比TCP更重要的地位。
1.2 UDP通信基本流程
设定好统一的端口号;
初始化绑定指定端口号的数据接收器;
指定接收方的IP地址;
准备好轻量数据;
发送数据至指定的IP地址;
数据接收器触发后续逻辑。
2. UDP局域网通信的Java实现
2.1 UDP广播
UDP广播的实现较为简单,其接收方的IP地址固定为255.255.255.255,端口号任选,保证发送方与接收方端口号一致且不与其他程序冲突即可,代码示例如下:
public class UDPManager {
public static final int BUFFER_SIZE = 2048;
public DatagramSocket socket;
public void init() {
try {
//先创建一个绑定了端口号为9527的DatagramSocket
socket = new DatagramSocket(9527);
//开启数据接收器
openReceiver();
//发送广播消息
sendBroadcast("Hello World!");
} catch (Exception e) {
e.printStackTrace();
}
}
public void openReceiver() {
//在子线程中循环接收数据
new Thread(new Runnable() {
@override
public void run() {
byte[] buffer = new byte[BUFFER_SIZE];
DatagramPacket dp = new DatagramPacket(buffer, BUFFER_SIZE);
while(socket != null) {
try {
socket.receive(dp);
System.out.println(new String(buffer));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start;
}
public void sendBroadcast(String dataStr) throws IOException {
//发送广播消息,消息内容为dataStr
if (socket != null) {
byte[] buffer = dataStr.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("255.255.255.255"), 9527);
socket.send(packet);
}
}
}
2.2 UDP单播
UDP单播的实现与广播类似,其接收方的IP地址需发送消息时传入,端口号任选,保证发送方与接收方端口号一致且不与其他程序冲突即可,在2.1中展示的UDPManager类中增加单播发送方法即可,代码示例如下:
public class UDPManager {
//···
public void sendSingle(String dataStr, String targetIP) throws IOException {
//发送单播消息,消息内容为dataStr,接收方IP地址为targetIP
if (socket != null) {
byte[] buffer = dataStr.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(targetIP), 9527);
socket.send(packet);
}
}
}
2.3 UDP多播
UDP多播的实现类似群聊,需要先加入一个指定IP的群组,之后消息往该IP发送即可,,端口号任选,单播与多播端口号不可相同,保证发送方与接收方端口号一致且不与其他程序冲突即可,并且需要在2.1中展示的UDPManager类中增加MulticastSocket类型的成员变量、修改init方法和openReceiver方法、增加对应的多播方法,代码示例如下:
public class UDPManager {
//···
//多播地址自选,在224.0.1.0~238.255.255.255之间即可
public static final String MULICAST_ADDRESS = "224.255.0.1"
public MulticastSocket multiSocket;
public void init() {
try {
//先创建一个绑定了端口号为9527的DatagramSocket
socket = new DatagramSocket(9527);
//创建一个绑定端口号为9528的MulticastSocket
multiSocket = new MulticastSocket(9528);
//开启数据接收器
openReceiver();
//加入多播群组
multiSocket.joinGroup(InetAddress.getByName(MULICAST_ADDRESS))
//发送广播消息
sendBroadcast("Hello World!");
} catch (Exception e) {
e.printStackTrace();
}
}
public void openReceiver() {
//···
//新建子线程接收多播数据
new Thread(new Runnable() {
@override
public void run() {
byte[] buffer = new byte[BUFFER_SIZE];
DatagramPacket dp = new DatagramPacket(buffer, BUFFER_SIZE);
while(multiSocket != null) {
try {
multiSocket.receive(dp);
System.out.println(new String(buffer));
} catch (IOException e) {
e.printStackTrace();
}
}
}
}).start;
}
//···
public void sendMultiple(String dataStr) throws IOException {
//发送多播消息,消息内容为dataStr
if (multiSocket != null) {
byte[] buffer = dataStr.getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName(MULICAST_ADDRESS), 9528);
multiSocket.send(packet);
}
}
}
2.4 局域网通信基础构想
在上述三种UDP通信方式的实现过程中,发现广播方式并不能送达局域网中所有接收者,非同一网段下的接收者将无法收到广播消息,而单播及多播是可以做到跨网段的。
初步设想,仅使用多播方式,局域网通信流程大致如下:
用户程序启动,UDP初始化完成;
加入组播,发送用户上线消息,暴露本机信息(IP地址等);
接收到用户上线消息的接收方将该用户加入在线用户列表,并再发送一次本机的用户上线消息;
用户触发消息发送,消息中附带本机信息(IP地址等)与指定接收方IP地址或是用户名等(可以是数组,指定多个接收方);
接收方收到消息,判断此消息指定接收方中是否有本机,若有则处理该消息,否则丢弃;
用户关闭程序,发送用户下线消息;
接收到用户下线消息的接收方将该用户移除在线用户列表。
3. Android平台同一wifi环境下的尝试
3.1 UDP通信方式上的问题
在Android平台上初步尝试了UDP的各个通信方式,发现多播方式受到了极大的影响,经多方查证并多次尝试多播的使用,最后放弃了在Android平台上使用多播方式,如读者有兴趣可以尝试解决一下。
3.2 安卓wifi局域网通信基础构想
参考之前的构想,多播方式无法使用的情况下,广播结合单播的方式成为我的备用方案,大致流程如下:
用户程序启动,UDP初始化完成;
发送广播,传输用户上线消息,暴露本机信息(IP地址等);
接收到广播的接收方将该用户加入在线用户列表,并向该用户发送一次本机的用户上线消息;
用户触发消息发送,以单播的方式发送给指定接收方的IP地址,消息中附带本机信息(IP地址等);
接收方收到消息,处理该消息。
用户关闭程序,发送用户下线消息;
接收到用户下线消息的接收方将该用户移除在线用户列表。
UDP局域网通信的Java实现及Android平台尝试的更多相关文章
- c# udp局域网通信
udp224.0.0.1 子网上的所有系统224.0.0.2 子网上的所有路由器224.0.0.12 dhcp服务器224.0.1.1 ntp224.0.1.24 wins服务器 http://www ...
- UDP广域网,局域网通信-原理分析,穿透技术
一.UDP局域网通信. 这个比较简单,关于局域网中的2台或者更多的计算机之间的UDP通信,网络上一大把,直接复制粘贴就可以使用,原理也非常简单.所以,本文不做详细介绍. 二.UDP广域通信(包括路由器 ...
- C#UDP广域网,局域网通信-原理分析
一.UDP局域网通信. 这个比较简单,关于局域网中的2台或者更多的计算机之间的UDP通信,网络上一大把,直接复制粘贴就可以使用,原理也非常简单.所以,本文不做详细介绍. 二.UDP广域通信(包括路由器 ...
- 《React Native 精解与实战》书籍连载「Android 平台与 React Native 混合开发」
此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...
- [Java] Tcp/udp 简单通信
本文转自 我自己的博客guozeyiblog.cn 欢迎来訪 效果图: //UDP通信 import java.awt.*; import java.awt.event.ActionEvent; i ...
- android的Binder通信机制java层浅谈-android学习之旅(88)
1.Service Manager的Java代理对象 在Java层中,Service Manager的代理对象类型为ServiceManagerProxy.它继承并且实现了IServiceManage ...
- Java 面试/笔试题神整理 [Java web and android]
Java 面试/笔试题神整理 一.Java web 相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并 ...
- 高性能 TCP/UDP/HTTP 通信框架 HP-Socket v4.1.1
HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/ ...
- 高性能 TCP/UDP/HTTP 通信框架 HP-Socket v4.1.2
HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/ ...
随机推荐
- NOIP提高组2016 D1T2 【天天爱跑步】
码了一个下午加一个晚上吧...... 题目描述: 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成 ...
- Python+Appium自动化测试(5)-appium元素定位常用方法
对于Android而言,查找appUI界面元素属性的工具有三种:appium desktop,uiautomatorviewer.bat,weditor.之前已经介绍过了weditor的使用,这里我将 ...
- IE下文件上传, SCRIPT5: 拒绝访问 问题
最近遇到一个比较奇葩的问题,某些ie浏览器在页面中上传文件时,无法上传.查看控制台报错: SCRIPT5: 拒绝访问. jquery-3.2.1.min.js, 行4 字符5725 .并且我的最新版I ...
- 基于Docker的MySql
MySQL Server安装教程 考虑到实际情况需要经常使用MySQL,为了方便大家能够快速基于Docker搭建MySQL这里以Linux下为例 进行说明,对于Windows用户来说直接通过查看官网H ...
- Linux基础命令列表
命令列表 A alias apt apt-get arp -n -s arping ab B bc basename bash -n -x bzip2 bunzip2 bzcat blkid brct ...
- springboot入门系列(三):SpringBoot教程之RabbitMQ示例
SpringBoot教程之RabbitMQ示例 SpringBoot框架已经提供了RabbitMQ的使用jar包,开发人员在使用RabbitMQ的时候只需要引用jar包简单的配置一下就可以使用Rabb ...
- 深入理解Java的抽象类和接口
对于面向对象来说,抽象是其重要特征之一.对于之中的抽象类和接口,两者有很多相似的地方,又有两者之间区别的地方. 用几个简单的例子让你快速的理解两者之间的概念和区别 鸣谢 一.抽象类 在了解抽象类之前, ...
- Windows下显示已经连过的Wifi密码
Windows下显示已经连过的Wifi密码 1. 打开cmd 2. netsh 3. wlan show profile 可以得到所有已经连过的wifi 4. wlan show pr ...
- 深入理解Java注解类型(@Annotation)
http://blog.csdn.net/javazejian/article/details/71860633 出自[zejian的博客] java注解是在JDK5时引入的新特性,鉴于目前大部分框 ...
- SpringBoot第三集:热部署与单元测试(2020最新最易懂)
SpringBoot第三集:热部署与单元测试(2020最新最易懂) 有兴趣的可以先参考附录简单了解SpringBoot自动装配流程. 一.SpringBoot开发热部署 项目开发中,你是否也遇到更新配 ...