【JavaSE】【网络编程】UDP数据报套接字编程

news2024/11/23 12:39:08

目录

  • 一、网络编程简介
  • 二、Socket套接字
  • 三、TCP/UDP简介
    • 3.1 有连接 vs 无连接
    • 3.2 可靠传输 vs 不可靠传输
    • 3.3 面向字节流 vs 面向数据报
    • 3.4 双向工 vs 单行工
  • 四、UDP数据报套接字编程
    • 4.1 API介绍
      • 4.1.1 DatagramSocket类
        • 4.1.1.1 构造方法
        • 4.1.1.2 主要方法
      • 4.1.2 DatagramPocket类
        • 4.1.2.1 构造方法
        • 4.1.2.2 主要方法
      • 4.1.3 使用上述类创建回显服务器-客户端
        • 4.1.3.1 回显服务器UdpEchoServer
        • 4.1.3.2 回显客户端UdpEchoClient

一、网络编程简介

网络编程:

网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。

网络编程涉及基本概念:

一次网络数据传输时:
发送端:数据的发送方进程,称为发送端。发送端主机即网络通信中的源主机。
接收端:数据的接收方进程,称为接收端。接收端主机即网络通信中的目的主机。
收发端:发送端和接收端两端,也简称为收发端。

请求和响应 :
一般来说,获取一个网络资源,涉及到两次网络数据传输:
第一次:请求数据的发送。
第二次:响应数据的发送。

客户端和服务端
服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。
客户端:获取服务的一方进程,称为客户端。

二、Socket套接字

Socket套接字:Socket套接字,是由系统提供用于网络通信的技术,是基于TCP/IP协议的网络通信的基本操作单元。基于Socket套接字的网络程序开发就是网络编程。

Socket套接字主要针对传输层协议划分为如下三类:

  1. 流套接字:使用传输层TCP协议。
  2. 数据报套接字:使用传输层UDP协议。
  3. 原始套接字:用于自定义传输层协议。

三、TCP/UDP简介

socket api :传输层提供给应用层的API。
传输层的两个核心协议是:TCP与UDP协议。

  • TCP协议:有连接,可靠传输,面向字节流,全双工的协议。
  • UDP协议:无连接,不可靠传输,面向数据报,全双工的协议。

3.1 有连接 vs 无连接

有/无连接:是一个抽象的概念,虚拟的逻辑上的连接。就像前面的链表的学习一样,物理上不连续,但通过节点之间的关联使其逻辑上连续。

TCP协议中:保存了对端的信息,让两个通信之间的设备有连接。就如AB通信,A保存B信息,B保存A信息。

UDP协议中:UDP本身不保存对端信息,但可以自己使用代码保存。

3.2 可靠传输 vs 不可靠传输

丢包: 网络上数据发生丢失的情况就是丢包。

传输中丢包情况造成原因:

  1. 当光/电/电磁信号,受到外界的干扰。
  2. 网络世界是通过交换机,路由器组建起来的。而交换机,路由器就像十字路口一样,当某个时间点,实际转发的数据超过设备能转发的上限的时候,就会“堵车”,造成丢包。

可靠传输:不是保证数据报100%到达,不造成一点丢失。而是尽可能提高传输成功的概率,如果丢包还会进行记录。

不可靠传输:在发出数据后就不管了。

3.3 面向字节流 vs 面向数据报

面向数据流:读写数据(读–>接收数据,写–> 发送数据)的时候,以字节为单位。支持读写任意长度,有粘包问题。
面向数据报:读写数据(读–>接收数据,写–> 发送数据)的时候,以一个数据报为单位。有长度限制。

3.4 双向工 vs 单行工

全双工:读写数据(读–>接收数据,写–> 发送数据),支持双向通信,能读能写。
单双工:面向数据流:读写数据(读–>接收数据,写–> 发送数据),只支持单向通信,要么读要么写。

四、UDP数据报套接字编程

计算机中的文件通常是一个广义的概念,文件除了指代一些我们常说的文件外,还能指代一些硬件设备。操作系统管理硬件设备也是抽象成文件。

4.1 API介绍

4.1.1 DatagramSocket类

DatagramSocket 是UDP Socket,⽤于发送和接收UDP数据报。

4.1.1.1 构造方法
方法签名方法说明
public DatagramSocket() throws SocketException创建⼀个UDP数据报套接字的Socket,绑定到本机任意⼀个随机端⼝(⼀般⽤于客⼾端)
public DatagramSocket(int port) throws SocketException创建⼀个UDP数据报套接字的Socket,绑定到本机指定的端⼝(⼀般⽤于服务端)
public DatagramSocket(int port, InetAddress laddr) throws SocketException创建⼀个UDP数据报套接字的Socket,绑定到指定的IP即laddr和端⼝port
public DatagramSocket(SocketAddress bindaddr) throws SocketException创建⼀个UDP数据报套接字的Socket,绑定到bindaddr指定的IP和端⼝
4.1.1.2 主要方法
方法签名作用
public void send(DatagramPacket p) throws IOException从此套接字发送数据报包(不会阻塞等待,直接发送)
public synchronized void receive(DatagramPacket p) throws IOException从此套接字接收数据报(如果没有接收到数据报,该⽅法会阻塞等待)
public void close()关闭此数据报套接字

4.1.2 DatagramPocket类

DatagramPacket是UDP Socket发送和接收的数据报。

4.1.2.1 构造方法
方法签名作用
public DatagramPacket(byte buf[ ], int length)构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)
public DatagramPacket(byte buf[ ], int offset, int length)构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)从buf的下标offset位置开始接收
public DatagramPacket(byte buf[], int offset, int length, SocketAddress address)构造⼀个DatagramPacket以⽤来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从offset到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号
public DatagramPacket(byte buf[ ], int offset, int length, InetAddress address, int port)构造⼀DatagramPacket以⽤来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP,port指定⽬的主机的端⼝号
public DatagramPacket(byte buf[ ], int length, SocketAddress address)构造⼀个DatagramPacket以⽤来发送数据报,发送的数据为字节数组(第⼀个参数buf)中,从0到指定⻓度(第⼆个参数length)。address指定⽬的主机的IP和端⼝号
public DatagramPacket(byte buf[ ], int length, InetAddress address, int port)构造⼀个DatagramPacket以⽤来接收数据报,接收的数据保存在字节数组(第⼀个参数buf)中,接收指定⻓度(第⼆个参数length)address指定⽬的主机的IP,port指定⽬的主机的端⼝号
4.1.2.2 主要方法
方法签名作用
public synchronized byte[ ] getData()获取数据报中的数据
public synchronized int getPort()从接收的数据报中,获取发送端主机的端⼝号;或从发送的数据报中,获取接收端主机端⼝号
public synchronized InetAddress getAddress()从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取接收端主机IP地址

4.1.3 使用上述类创建回显服务器-客户端

回显:请求是啥,相应就是啥。

4.1.3.1 回显服务器UdpEchoServer
  1. 先创建一个成员变量:Socket对象,用于接收发送数据报。private DatagramSocket socket = null;
  2. 构造方法,指定一个固定端口号给服务器使用,将Socket使用这个端口号实例化。
public UdpEchoServer(int port) throws SocketException{
        socket = new DatagramSocket(port);
    }
  1. 接下来在start方法中编写服务器实现逻辑。由于服务器是要7*24小时工作的,所以在一个死循环中实现。
  2. 读取请求并解析;
    4.1 构造一个DatagramPocket对象,初始化为0(不是null),用于保存UDP的载荷部分。
    DatagramPacket requestPacket = new DatagramPacket(new byte[2024],2024);
    4.2 读取请求socket.receive(requestPacket);
    4.3 把读取到有效数据的解析为字符串。
    通过getData方法获取DatagramPacket 中的字节数组,getLength方法获取DatagramPacket 有效数据长度,根据字节数组构造字符串。
    String request = new String(requestPacket.getData(), 0 ,requestPacket.getLength());
  3. 根据请求计算响应,由于是回显服务器,直接请求就是响应。
String response = product(request);

private String product(String request) {
        return request;
    }
  1. 把响应返回给客户端,通过getBytes方法拿到字符串中的字节数据,getBytes().length拿到字节长度,getSocketAddress方法拿到客户端的端口和IP。
socket.send(new DatagramPacket(request.getBytes(),request.getBytes().length,
requestPacket.getSocketAddress()));
  1. 打印一个日志记录此次交互过程。
System.out.printf([%s:%d],request:%s,response:%s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
  1. 总代码
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
public class UdpEchoServer {
    //先创建一个成员变量:Socket对象,用于接收发送数据报
    private DatagramSocket socket = null;

    //构造方法,指定一个固定端口号给服务器使用,将Socket使用这个端口号实例化
    public UdpEchoServer(int port) throws SocketException{
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        while (true) {
            //构造一个DatagramPocket对象,初始化为0(不是null),用于保存UDP的载荷部分。
            DatagramPacket requestPacket = new DatagramPacket(new byte[2024], 2024);
            //接收请求
            socket.receive(requestPacket);
            //把读取到有效数据的解析为字符串
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());

            //计算响应
            String response = product(request);
            //把响应返回给客户端
            socket.send(new DatagramPacket(request.getBytes(),request.getBytes().length,requestPacket.getSocketAddress()));
            //打印一个日志
            System.out.printf("[%s : %d], request:%s , response:%s\n",requestPacket.getAddress().toString(),
                    requestPacket.getPort(),request,response);
        }
    }

    private String product(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(6666);
        server.start();
    }
}

4.1.3.2 回显客户端UdpEchoClient
  1. 先创建一个成员变量:Socket对象,用于接收发送数据报private DatagramSocket socket = null;
  2. UDP 本身不保存对端的信息, 就自己的代码中保存一下.
	private String serverIp;
    private int port;
  1. 构造方法是要指定访问的服务器的地址。
public UdpEchoClient(String serverIp,int port) throws SocketException {
        this.serverIp = serverIp;
        this.port = port;
        socket = new DatagramSocket();
    }
  1. 从控制台读取用户输入的内容。
			System.out.println("请输入要传输的内容");
            Scanner scanner = new Scanner(System.in);
            if (!scanner.hasNext()) {
                    break;
            }
            String request =scanner.next();
  1. 发送数据报,把请求发送给服务器, 需要构造 DatagramPacket 对象。 构造过程中, 不光要构造载荷, 还要设置服务器的 IP 和端口号。
socket.send(new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),port));
  1. 接收服务器的响应
DatagramPacket responsePacket = new DatagramPacket(new byte[2024],2024);
socket.receive(responsePacket);
  1. 从服务器读取的数据进行解析, 打印出来.
String response = new String(responsePacket.getData(),0,responsePacket.getData().length);
            System.out.println(response);
  1. 总代码
import java.io.IOException;
import java.net.*;
import java.util.Scanner;

public class UdpEchoClient {
    //先创建一个成员变量:Socket对象,用于接收发送数据报
    private DatagramSocket socket = null;
    // UDP 本身不保存对端的信息, 自己的代码中保存一下
    private String serverIp;
    private int port;
    public UdpEchoClient(String serverIp,int port) throws SocketException {
        this.serverIp = serverIp;
        this.port = port;
        socket = new DatagramSocket();
    }
    public void start() throws IOException {
        while (true) {
            // 1. 从控制台读取用户输入的内容.
            System.out.println("请输入要传输的内容");
            Scanner scanner = new Scanner(System.in);
            if (!scanner.hasNext()) {
                    break;
            }
            String request =scanner.next();

            //  发送数据报.把请求发送给服务器, 需要构造 DatagramPacket 对象。 构造过程中, 不光要构造载荷, 还要设置服务器的 IP 和端口号。
            socket.send(new DatagramPacket(request.getBytes(),request.getBytes().length, InetAddress.getByName(serverIp),port));
            //接收服务器的响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[2024],2024);
            socket.receive(responsePacket);

            //从服务器读取的数据进行解析, 打印出来.
            String response = new String(responsePacket.getData(),0,responsePacket.getData().length);
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient client = new UdpEchoClient("127.0.0.1",6666);
        client.start();
    }
}

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

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

相关文章

MFC图形函数学习10——画颜色填充矩形函数

一、介绍绘制颜色填充矩形函数 前面介绍的几个绘图函数填充颜色都需要专门定义画刷,今天介绍的这个函数可以直接绘制出带有填充色的矩形。 原型1:void FillSolidRect(int x,int y,int cx,int cy,COLORREF color); 参数:&a…

macOS 无法安装第三方app,启用任何来源的方法

升级新版本 MacOS 后,安装下载的软件时,不能在 ”安全性与隐私” 中找不到 ”任何来源” 选项。 1. 允许展示任何来源 点击 启动器 (Launchpad) – 其他 (Other) – 终端 (Terminal): 打开终端后,输入以下代码回车: …

基于“开源 2+1 链动模式 S2B2C 商城小程序”的社区团购运作主体特征分析

摘要:本文聚焦社区团购运作主体,深入探讨便利连锁店型与社会力量型运作主体在社区团购中的特点,并结合“开源 21 链动模式 S2B2C 商城小程序”,分析其对社区团购的影响与作用机制,旨在为社区团购的进一步发展与优化提供…

Properties文件:Properties属性文件键值对的获取方法、如何写入信息到Properties属性文件、Properties对象的用法

目录 1、什么是Properties文件?和普通txt文件有什么区别? 2、读写Properties文件 2.1 代码演示-读取属性文件 2.2、代码演示-把键值对的数据写入到属性文件中去 1、什么是Properties文件?和普通txt文件有什么区别? 我们都知道…

枫清科技亮相 2024 中国 5G+工业互联网大会,推动 AI 赋能新型工业化

11 月 19 日,2024 中国 5G工业互联网大会在武汉盛大开幕,吸引了来自国内外的行业专家与领先企业。本次大会以“实数融合 智造翘楚”为主题,重点围绕 5G 与工业互联网的深度融合应用、人工智能、智能网联汽车等领域展开讨论与成果展示。作为行…

Spring Boot 3.x + OAuth 2.0:构建认证授权服务与资源服务器

Spring Boot 3.x OAuth 2.0:构建认证授权服务与资源服务器 前言 随着Spring Boot 3的发布,我们迎来了许多新特性和改进,其中包括对Spring Security和OAuth 2.0的更好支持。本文将详细介绍如何在Spring Boot 3.x版本中集成OAuth 2.0&#xf…

使用Python编写脚本,为Excel表格添加水印

简介 这是本人实习中的一个小任务,经过无数努力,终于搞出来了。网上很多资料和博客都是lese,完全没有理清楚水印在excel中的定义是什么,插个图片就是水印吗?当然不是!如果帮助到佬们请点个赞吧。 Ecxel中…

MacOS下的Opencv3.4.16的编译

前言 MacOS下编译opencv还是有点麻烦的。 1、Opencv3.4.16的下载 注意,我们使用的是Mac,所以ios pack并不能使用。 如何嫌官网上下载比较慢的话,可以考虑在csdn网站上下载,应该也是可以找到的。 2、cmake的下载 官网的链接&…

jspm东风锻造有限公司重大停管理系统

摘要 东风锻造有限公司重大停管理系统提供给员工和经理一个重大停信息管理的系统。本系统采用了B/S体系的结构,使用了java技术以及MYSQL作为后台数据库进行开发。系统主要分为系统管理员,员工和经理三个部分,系统管理员主要功能包括个人中心…

list =和addAll在List<实体类>数组的应用

实体类 A public class A {private String name;private Integer age;public String getName() {return name;}public void setName(String name) {this.name name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age age;} }用会报错 publi…

探索设计模式:原型模式

设计模式之原型模式 🧐1. 概念🎯2. 原型模式的作用📦3. 实现1. 定义原型接口2. 定义具体的原型类3. 定义客户端4. 结果 📰 4. 应用场景🔍5. 深拷贝和浅拷贝 在面向对象编程中,设计模式是一种通用的解决方案…

多目标优化算法:多目标极光优化算法(MOPLO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码

一、极光优化算法 极光优化算法(Polar Lights Optimization, PLO)是2024年提出的一种新型的元启发式优化算法,它从极光这一自然现象中汲取灵感。极光是由太阳风中的带电粒子在地球磁场的作用下,与地球大气层中的气体分子碰撞而产…

FPGA实现PCIE3.0视频采集转SFP光口千兆UDP网络输出,基于XDMA+GTH架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的所有工程源码总目录----方便你快速找到自己喜欢的项目我已有的PCIE方案1G/2.5G Ethernet Subsystem实现物理层方案1G/2.5G Ethernet PCS/PMA or SGMII Tri Mode Ethernet MAC实现物理层方案本博客方案的PCIE2.0版本 3、P…

40分钟学 Go 语言高并发:开发环境搭建与工程化实践

Day 01 - Go开发环境搭建与工程化实践 1. Go环境变量配置 1.1 重要的环境变量表格 环境变量说明示例值GOROOTGo语言安装根目录Windows: C:\goLinux/Mac: /usr/local/goGOPATH工作目录,包含src、pkg、binWindows: C:\Users\username\goLinux/Mac: ~/goGOBIN可执行…

【Mysql】函数-----窗口函数

1、介绍 Mysql 8.0 新增了窗口函数,窗口函数又被称为开窗函数,与orcale窗口函数相似,属于Mysql的一大特点。非聚合函数是相对于聚合函数来说的。聚合函数是一组数据计算后返回单个值(即分组)。非聚合函数一次只会处理…

【开源免费】基于SpringBoot+Vue.JS网上订餐系统(JAVA毕业设计)

本文项目编号 T 039 ,文末自助获取源码 \color{red}{T039,文末自助获取源码} T039,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析5.4 用例设计 六、核…

文件上传-阿里云OSS

使用 安装SDK <dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version> </dependency> 如果使用的是Java 9及以上的版本&#xff0c;则需要添加JAXB相关依赖。添加…

大数据实验4-HBase

一、实验目的 阐述HBase在Hadoop体系结构中的角色&#xff1b;能够掌握HBase的安装和配置方法熟练使用HBase操作常用的Shell命令&#xff1b; 二、实验要求 学习HBase的安装步骤&#xff0c;并掌握HBase的基本操作命令的使用&#xff1b; 三、实验平台 操作系统&#xff1…

【前端】JavaScript 变量引用、内存与数组赋值:深入解析三种情景

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;场景一&#xff1a;直接赋值与重新引用为什么结果不是 [3, 4, 5]&#xff1f;1. 引用与赋值的基本概念2. 图示分析 关键总结 &#x1f4af;场景二&#xff1a;引用指向的变化为什么…

微信小程序的医院预约挂号系统

摘 要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;医院预约挂号系统当然不能排除在外。医院预约挂号系统是在实际应用和软件工程的开发原理之上&#xff0c;运用微信开发者、java语言以及S…