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/ ...
随机推荐
- Word+Excel 问题及解决
[Word] 快捷操作 (1)每个字后面都有换行符的处理办法: 替换:∧p -> 空格 (2)隐藏Word文档中的换行符: word选项 -> 显示 -> 段落标记 [Excel]
- 多测师讲解pyhon__hashlib_高级讲师肖sir
一.加密,加密成16进制的字符串 # import hashlib # 导入hashlib模块# md = hashlib.md5() # 获取一个md5加密算法对象# md.update('需要加密 ...
- bash 括号使用
Bash 括号多种使用方式 ${} 变量初始化 ${param:-string} 若变量param为空或者未定义,则用在命令行中用string来替换${param:-string} 否则变量param ...
- Linux ALSA音频库(二) 环境测试+音频合成+语音切换 项目代码分享
1. 环境测试 alsa_test.c #include <alsa/asoundlib.h> #include <stdio.h> // 官方测试代码, 运行后只要有一堆信息 ...
- go 加锁
package mainimport ( "fmt" "math/rand" "sync" "time")var tic ...
- centos8安装kafka(单机方式)
一,下载kafka 1,官网地址 http://kafka.apache.org/downloads.html 2,下载 [root@localhost source]# wget http://mi ...
- 第十二章 LNMP架构之分离数据库
一.课程回顾 1.搭建LNMP环境 1.配置官方源2.yum安装依赖3.yum安装nginx4.配置nginx5.创建用户6.启动并加入开机自启7.上传安装包8.解压安装包9.卸载旧版本PHP10. ...
- fiddler 实用小技巧
1.添加查看响应时间
- C# XML解析
摘自:http://www.cnblogs.com/RiseSoft/archive/2012/03/17/2404007.html 之前在项目中处理的都是一些小数据量的XML文件,都是直接用.Net ...
- Linux命令之date +%F
date命令显示当前日期 date +%F显示当前日期 [10:02:52 root@C8[ 2020-06-16DIR]#touch `hostname`_`date +%F`.log [10:03 ...