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/ ...
随机推荐
- 把python文件打包成可执行文件(win10实验成功)
总是有人来找我帮看下工单状态,又懒得写页面展示出来,干脆打包成exe文件好啦 打包很简单,难点在于安装pyinstaller这个依赖包,主要是网络问题~ 我也是参考别人的博文,别人的文章写得很详细,我 ...
- c++ 西安交通大学 mooc 第十三周基础练习&第十三周编程作业
做题记录 风影影,景色明明,淡淡云雾中,小鸟轻灵. c++的文件操作已经好玩起来了,不过掌握好控制结构显得更为重要了. 我这也不做啥题目分析了,直接就题干-代码. 总结--留着自己看 1. 流是指从一 ...
- shell-变量的数值运算与特殊应用expr
1. expr(evaluate expressions)命令的用法: expr命令一般用于整数值,当也可用于字符串,用来求表达式变量的值,同时expr也是一个手工命令行计算器. 语法:expr ex ...
- Windows下的git服务器搭建
时间一晃又是两个月过去了,我好像在写博客这方面有点懒,= .= 主要也是没啥好写的,项目上的事情又不能写,能写的东西实在太少. 前两个月领导花巨资申请了一个服务器,让我搞git服务器来管理代码,花了几 ...
- 安装clion
转战c语言,首先搞定编辑器,之前用的pycharm所以就直接用clion了,但是装完不能直接用参考 https://www.cnblogs.com/lyc94620/p/9581786.html 所以 ...
- Pyrhon-OS库
import os 导入OS模块 print(os.getcwd()) #获取当前路径 print(os.listdir()) #当前路径下文件信息 关于路径 Windows 下的路径采用 (\) 在 ...
- .net 添加打印 源代码
<div style="margin-top: auto; text-align: center;" id="buttondiv"> <obj ...
- Python之数据类型总结
1.字符串 2.数字 3.列表 4.元组 5.字典 可变 or 不可变 1:可变:列表.字典 2:不可变:字符串,数字,元组 访问顺序 1.直接访问:数字 2.顺序访问:字符串,列表,元组 3.映射访 ...
- HEAP CORRUPTION DETECTED:after Normal block错误方法解决
一:问题描述: 出现的问题如下: 二:问题产生的原因说明 该问题发生于操作堆内存的时候.产生该问题的原因是:你实际使用的内存大小超出了你实际申请的内存大小,在释放内存的时候就会发生该问题. 举个例子: ...
- 利用Gitee转接GitHub下载加速 简简单单 - 快快乐乐
利用Gitee转接GitHub下载加速 简简单单 - 快快乐乐 JERRY_Z. ~ 2020 / 10 / 26 转载请注明出处!️ 目录 利用Gitee转接GitHub下载加速 简简单单 - 快快 ...