局域网通信已经很少被他人所提及了,我曾经还尝试过通过蓝牙构建通信网络,这次有机会尝试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通信基本流程

  1. 设定好统一的端口号;

  2. 初始化绑定指定端口号的数据接收器;

  3. 指定接收方的IP地址;

  4. 准备好轻量数据;

  5. 发送数据至指定的IP地址;

  6. 数据接收器触发后续逻辑。

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通信方式的实现过程中,发现广播方式并不能送达局域网中所有接收者,非同一网段下的接收者将无法收到广播消息,而单播及多播是可以做到跨网段的。

初步设想,仅使用多播方式,局域网通信流程大致如下:

  1. 用户程序启动,UDP初始化完成;

  2. 加入组播,发送用户上线消息,暴露本机信息(IP地址等);

  3. 接收到用户上线消息的接收方将该用户加入在线用户列表,并再发送一次本机的用户上线消息;

  4. 用户触发消息发送,消息中附带本机信息(IP地址等)与指定接收方IP地址或是用户名等(可以是数组,指定多个接收方);

  5. 接收方收到消息,判断此消息指定接收方中是否有本机,若有则处理该消息,否则丢弃;

  6. 用户关闭程序,发送用户下线消息;

  7. 接收到用户下线消息的接收方将该用户移除在线用户列表。

3. Android平台同一wifi环境下的尝试

3.1 UDP通信方式上的问题

在Android平台上初步尝试了UDP的各个通信方式,发现多播方式受到了极大的影响,经多方查证并多次尝试多播的使用,最后放弃了在Android平台上使用多播方式,如读者有兴趣可以尝试解决一下。

3.2 安卓wifi局域网通信基础构想

参考之前的构想,多播方式无法使用的情况下,广播结合单播的方式成为我的备用方案,大致流程如下:

  1. 用户程序启动,UDP初始化完成;

  2. 发送广播,传输用户上线消息,暴露本机信息(IP地址等);

  3. 接收到广播的接收方将该用户加入在线用户列表,并向该用户发送一次本机的用户上线消息;

  4. 用户触发消息发送,以单播的方式发送给指定接收方的IP地址,消息中附带本机信息(IP地址等);

  5. 接收方收到消息,处理该消息。

  6. 用户关闭程序,发送用户下线消息;

  7. 接收到用户下线消息的接收方将该用户移除在线用户列表。

UDP局域网通信的Java实现及Android平台尝试的更多相关文章

  1. 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 ...

  2. UDP广域网,局域网通信-原理分析,穿透技术

    一.UDP局域网通信. 这个比较简单,关于局域网中的2台或者更多的计算机之间的UDP通信,网络上一大把,直接复制粘贴就可以使用,原理也非常简单.所以,本文不做详细介绍. 二.UDP广域通信(包括路由器 ...

  3. C#UDP广域网,局域网通信-原理分析

    一.UDP局域网通信. 这个比较简单,关于局域网中的2台或者更多的计算机之间的UDP通信,网络上一大把,直接复制粘贴就可以使用,原理也非常简单.所以,本文不做详细介绍. 二.UDP广域通信(包括路由器 ...

  4. 《React Native 精解与实战》书籍连载「Android 平台与 React Native 混合开发」

    此文是我的出版书籍<React Native 精解与实战>连载分享,此书由机械工业出版社出版,书中详解了 React Native 框架底层原理.React Native 组件布局.组件与 ...

  5. [Java] Tcp/udp 简单通信

    本文转自  我自己的博客guozeyiblog.cn 欢迎来訪 效果图: //UDP通信 import java.awt.*; import java.awt.event.ActionEvent; i ...

  6. android的Binder通信机制java层浅谈-android学习之旅(88)

    1.Service Manager的Java代理对象 在Java层中,Service Manager的代理对象类型为ServiceManagerProxy.它继承并且实现了IServiceManage ...

  7. Java 面试/笔试题神整理 [Java web and android]

    Java 面试/笔试题神整理 一.Java web 相关基础知识 1.面向对象的特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关的那些方面,以便更充分地注意与当前目标有关的方面.抽象并 ...

  8. 高性能 TCP/UDP/HTTP 通信框架 HP-Socket v4.1.1

    HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/ ...

  9. 高性能 TCP/UDP/HTTP 通信框架 HP-Socket v4.1.2

    HP-Socket 是一套通用的高性能 TCP/UDP/HTTP 通信框架,包含服务端组件.客户端组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP/HTTP 通信系统,提供 C/ ...

随机推荐

  1. vue实现语音播报功能

    1,创建一个js文件 (voicePrompt.js) function voicePrompt (text){ new Audio('http://tts.baidu.com/text2audio? ...

  2. NOI 2012 【迷失游乐园】

    这道题,额,反正我是刚了2天,然后就萎了......(是不是觉得我很菜) 题目描述: 放假了,小Z觉得呆在家里特别无聊,于是决定一个人去游乐园玩. 进入游乐园后,小Z看了看游乐园的地图,发现可以将游乐 ...

  3. Informatica报错“表或视图不存在”的某种原因

    软件版本:9.6.1 背景:测试将OLTP数据库的用户信息表(CUST_INFO)抽取到DW库(DW_CUST_INFO) 问题:工作流启动后,报错RR_4035,并告知表或视图不存在 分析:在导入源 ...

  4. vue超出8个字符,显示省略号

    显示的数据

  5. SpringBoot使用activiti自定义流程demo解析

    环境搭建[这里直接讲解自定义流程] 集成 Activiti Modeler 下载源码 我这里选用的是 Activiti 5.23.0 版本的页面,下载 zip,解压 Activiti 5.23.0 源 ...

  6. 多测师讲解selenium _a标签定位()_高级讲师肖sir

    shift+ctrl+c 快捷键  调出元素

  7. 关于.netMVC 出现@ViewBag 出现错误(波浪红线)的解决方法

    解决vs2015.vs2013解决mvc5 viewbag问题 1.关闭vs2015或者vs2013 打开我的电脑或者文件夹 2.打开我的电脑 在地址栏输入 %UserProfile%\AppData ...

  8. html学习(1)

    认识html标签 1.<h1></h1>就是标题标签,<p></p>是段落标签,img是图片标签.  2.html中的标签一般都是成对出现的,分开始标签 ...

  9. spring boot:多个filter/多个interceptor/多个aop时设置调用的先后顺序(spring boot 2.3.1)

    一,filter/interceptor/aop生效的先后顺序? 1,filter即过滤器,基于servlet容器,处于最外层, 所以它会最先起作用,最后才停止 说明:filter对所有访问到serv ...

  10. linux(centos8):prometheus使用mtail监控错误日志

    一,mtail的用途? mtail :从应用程序日志中提取指标以导出到时间序列数据库或时间序列计算器 它是一个google开发的日志提取工具,用途就是: 实时读取应用程序的日志. 再通过自己编写的脚本 ...