Java网络编程——UDP通信原理

news2024/11/6 7:34:21

一、TCP和UDP概述

传输层通常以TCP和UDP协议来控制端点与端点的通信

TCPUDP
协议名称传输控制协议用户数据包协议
是否连接面向连接的协议。数据必须要建立连接无连接的协议,每个数据报中都给出完整的地址信息,因此不需要事先建立发送方和接受方的连接
是否可靠可靠协议。确保收方完全地获取发送方所发送的全部数据不可靠协议。发送方所发送的数据报并不一定以相同的次序到达接收方。
可以传输的数据大小传输数据大小不受限制。一旦连接建立,双方可以按统一的格式传输大的数据传输数据时是有大小限制的。每个被传输的数据报必须限定在64KB之类
数据传输方式IO流DatagramPacket

二、UDP

1.UDP通信概述

UDP协议是一种对等通信的实现,发送方只需要接受方的IP(地址)和Port(端口),就可以直接向它发送数据,不需要线连接。每个程序都可以作为服务器,也可以作为客户端。UDP是一种无连接的传输协议,每个数据报的大小限定在64KB以内。数据报是一个在网络上发送的独立信息,它的到达。到达时间以及内容本身等都不能得到保证。这种传输方式是无序的,也不能确保绝对的安全可靠,但它很简单也具有较高的效率。
使用UDP协议进行数据传输是,需要将需要传输数据定义为数据报(DatagramPaket),在数据报中指明数据所要到达Socket(主机地址和端口号),然后再将数据报发送出去。实例化DatagramPacket时使用参数port和没有使用参数port的区别在与,提供port的一方可以让别人主动发送消息过来,而没有参数port的则会在发送消息时自动绑定一个本地没有使用的端口。在接收到发送的数据报(DatagramPaket)时,不仅可以获取数据,还可以获得发送方的IP和Port,这样就可以向发送方发送数据,因此,本质上二者是对等的。

2.UDP通信特点

1、UDP是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的原地址或目的地址,它在网络上任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
2、UDP不属于连接型协议,因而具有资源消耗小,处理速度快的优点,所以通常音频视频和普通数据在传输时使用UDP较多,因为它们即使偶尔丢一两个数据包,也不会对接收结果产生太大的影响。

3.UDP通信传输实现的基石

UDP通信的Socket使用DatagramSocket类实现,数据报使用DatagramPaket实现

3.1、DatagramPake常用方法

InetAddress getAddress()得到发送方IP地址
int getPort()得到发送方的端口号
byte[] getData()返回接收缓冲区,这是一个byte[]
int getLength()接收字节的真实大小,通常用于从byte[]中提取出有效数据
int getOffset()返回将要发送或则接收的数据偏移量

3.2、DatagramSocket常用方法

DatagramSocket()空构造函数
DatagramSocket(int port)指定通信端口
void receive(DatagramPaket p)接收数据报
void send(DatagramPaket p)发送数据报
void close()关闭Socket

4.UDP通信实现原理

无论一个UDP通信程序的功能多么功能齐全,程序多么复杂,七基本结构都是一样的,都包括以下四个基本步骤
1、在接收端指定一个端口号来创建DatagramSocket,然后创建一个接收数据报(DatagramPaket),使用recevie方法等待发送方请求报文,这将阻塞服务器线程
2、在发送方创建一个DatagramSocket,使用接收方的IP和端口来创建发送数据报(DatagramPaket),使用send方法发送。现在接收方的recevie方法被唤醒,同时会将发送方的数据报内容填充到接收方的DatagramPaket中。
3、接收方从发送方的数据报中获得发送方的IP和端口,使用它们构造一个发送数据报,然后发送给发送方,这样就实现了发送方和接收方的通信
4、在通信完成后,在客服端和服务端中分别关闭Socket

5.UDP通信原理(代码实现)

代码如下(发送端):

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class SendMessage {

public static void main(String[] args) throws Exception {
// 创建发送端Socket对象
DatagramSocket sendSocket = new DatagramSocket();
// 准备需要发送的数据
String message = "hello";
// 创建一个缓冲区
byte[] messageByte = message.getBytes();
// 获取缓冲区中数据的真实长度
int messageLen = message.length();
// InetAddress实例化获取本机通信地址
InetAddress address = InetAddress.getLocalHost();
// 设置通信端口号
int port = 12345;
// 打包数据
DatagramPacket sendPacket = new DatagramPacket(messageByte, messageLen, address, port);
// 发送数据
sendSocket.send(sendPacket);
// 发送端等待接收端成功接收信息后返回的回应
// 创建一个缓冲区,容量尽量设置大一点因为不知道发送过来的信息有多大
byte[] recevieByte = new byte[1024*10];
int len = recevieByte.length;
// 接收数据报
DatagramPacket receivePacket = new DatagramPacket(recevieByte, len);
// 接收数据
sendSocket.receive(receivePacket);
// 获取接收端发送过来的真实长度以及数据
byte[] data = receivePacket.getData();
int length = receivePacket.getLength();
String receiveData = new String(data,0,length);
// 获取发送者的IP
address = receivePacket.getAddress();
String ip = address.getHostAddress();
System.out.println("接收来自:"+ip+"的数据,内容是:"+receiveData);
// 关闭资源
sendSocket.close();
}
}

代码如下(接收端):

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class RecevieMessage {

public static void main(String[] args) throws Exception {
// 接收消息的端口(与发送端保持一致)
int port = 12345;
DatagramSocket recevieSocket = new DatagramSocket(port);
// 设置缓冲区接收发过来的信息
byte[] receiveByte = new byte[1024*10];
int len = receiveByte.length;
// 接收数据报
DatagramPacket receviePacket = new DatagramPacket(receiveByte, len);
// 接收数据
recevieSocket.receive(receviePacket);
// 获取实际接收到的数据及其大小
byte[] data = receviePacket.getData();
int length = receviePacket.getLength();
String receiveData = new String(data,0,length);
// 获取发送者的IP
InetAddress address = receviePacket.getAddress();
String ip = address.getHostAddress();
System.out.println("接收来自:"+ip+"的数据,内容是:"+receiveData);
// 接收端接收到信息后发送一条确认接收的消息到发送端
String message = "OK";
byte[] messageByte = message.getBytes();
int messageLength = message.length();
// 从已收到的数据报中获取IP和port
address = receviePacket.getAddress();
int port1 = receviePacket.getPort();
//构造新数据报
DatagramPacket sendPacket = new DatagramPacket(messageByte, messageLength, address, port1);
// 发送数据
recevieSocket.send(sendPacket);
// 关闭资源
recevieSocket.close();
}
}

发送端输出结果:

接收端输出结果:

总结

注意:在发送端与接收端启动测试时最好最好先启动接收端,因为这样才能确保信息能发送出去,接收端能接收到信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1395451.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

200SMART作为智能控制器和智能设备使用

200SMART固件版本在V2.5以上的标准型CPU都支持PROFINET IO控制器和IO设备使用。 S7-200SMART作为智能设备仅支持1个IO控制器,可配置的输入输出存储区都为128个字节,地址范围分别为I(Q)1152.0到I(Q)1279.7;每个CPU支持最多8个PROFINET IO设备&#xff0c…

CentOS 6.10 安装图解

特特特别的说明 CentOS发行版已经不再适合应用于生产环境,客观条件不得不用的话,优选7.9版本,8.5版本次之,最次6.10版本(比如说Oracle 11GR2就建议在6版本上部署)! 引导和开始安装 选择倒计时结…

【Python】如何快速知道当前python所用库的路径

【背景】 项目一多,python环境就开始互相影响。有时需要快速知道当前的环境用的库,也就是site-pachage是哪个路径下的。 【方法】 打开相应的Python.exe,进入python命令行,输入: import sys print(sys.path)结果类…

canal server初始化源码分析

CanalLauncher类是canal server端启动的入口类,跟随代码进行深入。 在开始之前,我们可以先了解下, canal 配置方式 ManagerCanalInstanceGenerator: 基于manager管理的配置方式,实时感知配置并进行server重启Spring…

Java-初识正则表达式 以及 练习

目录 什么是正则表达式? 1. 正则表达式---字符类(一个大括号匹配一个字符): 2. 正则表达式---预字符类(也是匹配一个字符): 正则表达式---数量词 (可以匹配多个字符)…

android studio 连接 夜神模拟器方法

android studio 连接 夜神模拟器方法 1、打开cmd 2、输入夜神模拟器的安装地址,至bin目录下 3、输入连接指令:nox_adb.exe connect 127.0.0.1:62001 4、连接成功会提示successfully 5、打开Android Studio,会就会出现连接的模拟器。

C#,入门教程(07)——软件项目的源文件与目录结构

上一篇: C#,入门教程(06)——解决方案资源管理器,代码文件与文件夹的管理工具https://blog.csdn.net/beijinghorn/article/details/124895033 创建新的 C# 项目后, Visual Studio 会自动创建一系列的目录与文件。 程序员后面的工…

Opencv小项目——手势数字刷TIKTOK

​ 写在前面: 很久没更新了,之前的实习的记录也算是烂尾了,但是好在自己的实习记录还是有的,最近也忙碌了很多,终于放假了,今天下午正好没事,闲来无事就随便做个小玩意吧。 思来想去&#xff…

python算法与数据结构(搜索算法和拓扑排序算法)---深度优先搜索

课程目标 了解树/图的深度遍历,宽度遍历基本原理;会使用python语言编写深度遍历,广度遍历代码;掌握拓扑排序算法 搜索算法的意义和作用 搜索引擎 提到搜索两个子,大家都应该会想到搜索引擎,搜索引擎的基…

android 和 opencv 开发环境搭建

本文详细说明给android项目添加opencv库的详细步骤,并通过实现图片灰度化来查看配置是否成功。 下载OPENCV ANDROID SDK 到官网下载 打开 https://opencv.org/releases/ 选择android,下载完成后解压出下面的文件: 安装android sdk 和 ndk …

Tide Quencher 7.2 CPG 500A ,TQ7.2 CPG 500A,可以提高荧光标记物的淬灭效果

您好,欢迎来到新研之家 文章关键词:荧光淬灭剂Tide Quencher 7.2 CPG 500A,Tide Quencher 7.2 CPG 500A ,TQ7.2 CPG 500A 一、基本信息 产品简介:The fluorescence quencher Tide Quencher 7.2 CPG 500A can quench…

Android Dialog setCanceledOnTouchOutside失效,点击dialog外面不消失

前言:有一个需求需要点击dialog外面要消失,本来以为很简单结果设置了一直未生效 setCanceledOnTouchOutside(true); 问了半天chat-gpt4结果给的答案都不明显 查看代码发现设置了style,于是尝试去除这个style,结果点击setCancele…

用Go plan9汇编实现斐波那契数列计算

斐波那契数列是一个满足递推关系的数列,如:1 1 2 3 5 8 ... 其前两项为1,第3项开始,每一项都是其前两项之和。 用Go实现一个简单的斐波那契计算逻辑 func fib(n int) int {if n 1 || n 2 {return 1}return fib(n-1) fib(n-2) …

【leetcode】消失的数字

大家好,我是苏貝,本篇博客带大家刷题,如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️ 目录 1.暴力求解法2.采用异或的方法(同单身狗问题)3.先求和再减去数组元素 点击查看…

【机器学习300问】12、为什么要进行特征归一化?

当线性回归模型的特征量变多之后,会出现不同的特征量,然而对于那些同是数值型的特征量为什么要做归一化处理呢? 一、为了消除数据特征之间的量纲影响 使得不同指标之间具有可比性。例如,分析一个人的身高和体重对健康的影响&…

【物以类聚】给el-image预览多张图片增加提示文字,让每张图片有所分类

【物以类聚】给el-image预览多张图片增加提示文字,让每张图片有所分类 一、需求二、el-image三、实施步骤3.1 导包3.2 改造3.3 引入 三、效果 一、需求 点击地图上的一张图片,弹出所有相关的图片资源,图片资源上显示每个图片的所属类型。 二…

22k+star一款自托管的开源的的好用的碎片化笔记软件 Memos超级详细部署教程

目录 1.拉取镜像 2.启动 3.体验 4.源码地址 1.拉取镜像 docker pull neosmemo/memos:stable 2.启动 创建目录 mkdir -p /opt/memos/ 启动 docker run -d --name memos -p 10006:5230 -v /opt/memos/:/var/opt/memos neosmemo/memos:stable 3.体验 浏览器输入下面地址…

2023年全球软件架构师峰会(ArchSummit深圳站):核心内容与学习收获(附大会核心PPT下载)

本次峰会是一次重要的技术盛会,旨在为全球软件架构师提供一个交流和学习的平台。本次峰会聚焦于软件架构的最新趋势、最佳实践和技术创新,吸引了来自世界各地的软件架构师、技术专家和企业领袖。 在峰会中,与会者可以了解到数字化、AIGC、To…

彩超框架EchoSight开发日志记录

EchoSight开发记录 蒋志强 我会不定期的更新 开发进展。最近更新进展于2024年1月15日 1.背景 由于某些不可抗逆的原因,离开了以前的彩超大厂,竞业在家,难得有空闲的时间。我计划利用这段时间 自己独立 从零开始 搭建一套 彩超系统的软件工…

GLM-4多模态重磅更新!摸着OpenAI过河!

智谱CEO张鹏说:OpenAI摸着石头过河,我们摸着OpenAI过河。 摸来摸去摸了一年,以每3-4个月升级一次基座模型的速度,智谱摸着OpenAI过河的最新成绩到底怎么样?真如所说吗? 听到GLM-4发布的当天,我就…