Socket套接字(UDP数据报)篇

Socket

  • 概念
    • 数据报套接字
      • DatagramSocket
      • DatagramPacket
      • InetSocketAddress
  • 小结

概念

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

数据报套接字

使用的是UDP(User Datagram Protocol)协议,传输层协议.

  • 无连接
  • 不可靠传输
  • 面向数据报
  • 全双工

对于UDP协议来说,具有无连接,面向数据报的特征,每次都是没有建立连接,并且一次性发送全部数据报,并一次性接收全部数据报.
java使用UDP协议通信,基于DatagramSocket类创建数据报套接字,并使用DatagramPacket作为发送或接收的UDP数据报.

DatagramSocket

DatagramSocket是UDP Socket,用于发送和接收UDP数据报.

DatagramSocket构造方法:

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口(一般用于客户端)
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到指定端口(一般用于服务器端)

DatagramSocket方法:

方法签名方法说明
void receive(DatagramSocket p)就收套接字数据报,没有则会阻塞等待
void send(DatagramSocket p)发送套接字数据报
void close()关闭数据报套接字

DatagramPacket

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

DatagramPacket构造方法:

方法签名方法说明
DatagramPacket(byte[] buf, int length)这是接收数据报,接收的数据保存在byte数组中,指定接收长度
DatagramPacket(byte[] buf, int offset, int length, SocketAddress address)这是发送数据报,发送的数据时字节数组,从0到指定长度,address指定目的主机的IP和端口号

DatagramPacket方法:

方法签名方法说明
InetAddress getAddress()从接受的数据报中,获取发送端主机IP地址.或者从发送的数据报中,获取接收端主机的IP地址
int getPort()从接受的数据报中,获取发送端主机的端口号.或者从发送的数据报中,获取接收端主机的端口号
byte[] getData()获取数据报中的数据

InetSocketAddress

InetSocketAddress(SocketAddress的子类) 构造方法:

方法签名方法说明
InetSocketAddress(InetAddress addr, int port)创建一个Socket地址,包含IP地址和端口号

下面写一个回显服务器案例供参考:

// 服务器
public class UdpEchoServer {
    private DatagramSocket socket = null;
    public UdpEchoServer(int port) throws SocketException {
        // 根据端口号构造, 端口号被占用的时候,会报错
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            // 反复的,长期的反应客户端的请求处理的逻辑
            // 1. 读取请求,并解析。
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            // 后续客户端必须发送文本文件,才能这样转字符串
            String request = new String(requestPacket.getData(),0, requestPacket.getLength());
            // 2. 根据请求,计算相应
            String response = process(request);
            // 3. 把响应返回给客户端
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),0,response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            System.out.printf("[%s:%d] req: %s, resp: %s\n", requestPacket.getAddress().toString(),requestPacket.getPort(),
                    request,response);
        }
    }

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

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

相信仔细看完的小伙伴注意到了,socket对象并没有调用close来关闭,因为此时整个程序
只有一个socket,这个对象的生命周期非常长,是跟随整个程序的.
socket对象->系统中的socket文件->文件描述符
进程结束,就把pcb回收了,文件描述符也随之销毁了.
但是如果有多个socket对象,需要频繁创建释放,一定要去进行close操作.

// 客户端
public class UDPEchoClient {
    private DatagramSocket socket = null;

    private String serverIp;
    private int serverPort;

    public UDPEchoClient(String ip, int port) throws SocketException {
        this.serverIp = ip;
        this.serverPort = port;
        // 随机端口号
        socket = new DatagramSocket();
    }

    // 让客户端反复地读取控制台内容,把内容构造成UDP请求,发给服务器
    public void start() throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("客户端启动");
        while (true) {
            // 1.从控制台输入
            System.out.println("-> ");
            String request = scanner.nextLine();
            // 2.构造请求对象,发给服务器
            // 使用InetAddress的静态方法,getByName来进行构造(工厂模式)
            // InetAddress.getByName(serverIp),serverPort): 要发送的ip和端口
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),0,request.getBytes().length,
                    InetAddress.getByName(serverIp),serverPort);
            socket.send(requestPacket);
            // 3.客户端读取响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(responsePacket);
            String response = new String(responsePacket.getData(),0, responsePacket.getLength());
            // 4. 显示到屏幕上
            System.out.println(response);
        }
    }

    public static void main(String[] args) throws IOException {
    	// 端口号和服务器端一致
        UDPEchoClient client = new UDPEchoClient("127.0.0.1", 999);
        client.start();
    }
}

在这里插入图片描述

小结

本次总结了UDP套接字数据报的相关内容,TCP套接字放到下一章博客中.
希望有收获的小伙伴多多支持.

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

IGM焊接机器人RTE 495伺服电机维修详情一览

在当今科技迅速发展的时代,机器人已成为各行各业不可或缺的重要工具。IGM机器人便是其中之一,其工业机械手伺服马达作为机器人的关键部件,确保机器人能够高效、稳定地运行。当出现IGM焊接机器人RTE 495伺服电机故障问题时,及时进行…

【推荐】2024年必备的技术学习网站

在学习 Java 的过程中,你都在用哪些网站查找资料和学习呢?以下是 V 哥在日常工作和学习中,经常会使用到的网站,有哪些是与 V 哥不约而同都在用的呢,下面来一一介绍一下: 1、百度开发者搜索 你是不是日常在…

[Algorithm][分治 - 归并排序][排序数组][交易逆序对的总数][计算右侧小于当前元素的个数][翻转对]详细讲解

目录 0.原理讲解1.排序数组1.题目链接2.代码实现 2.交易逆序对的总数1.题目链接2.算法原理详解3.代码实现 3.计算右侧小于当前元素的个数1.题目链接2.算法原理详解3.代码实现 4.翻转对1.题目链接2.算法原理详解3.代码实现 0.原理讲解 归并排序的流程充分的体现了**「分⽽治之」…

使用CSgetshell到3389端口远程桌面

中间使用了这个Akagi64.exe提权,网上可以找到,高版本的cs网上也可以找到。

Linux系统编程---线程池并发服务器

模型原理分析: 线程池的关键优势在于它减少了每次任务执行时创建和销毁线程的开销 线程池的组成主要分为 3 个部分,这三部分配合工作就可以得到一个完整的线程池: 1. 任务队列,存储需要处理的任务,由工作的线程来处理…

Linux网络服务-DHCP

一、DHCP工作原理 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议):用于自动获取IP地址 1.客户端会发送一个广播DHCP Discover报文去寻找DHCP服务器 2.客户端只会接收第一个回复的DHCP服务器的报文 3.服务器会发…

MATLAB非均匀网格梯度计算

在matlab中,gradient函数可以很方便的对均匀网格进行梯度计算,但是对于非均匀网格,但是gradient却无法求解非均匀网格的梯度,这一点我之前犯过错误。我之前以为在gradient函数中指定x,y等坐标,其求解的就是…

Python异步Redis客户端与通用缓存装饰器

前言 这里我将通过 redis-py 简易封装一个异步的Redis客户端,然后主要讲解设计一个支持各种缓存代理(本地内存、Redis等)的缓存装饰器,用于在减少一些不必要的计算、存储层的查询、网络IO等。 具体代码都封装在 HuiDBK/py-tools: …

Ubuntu TeamViewer安装与使用

TeamViewer是一款跨平台的专有应用程序,允许用户通过互联网连接从全球任何地方远程连接到工作站、传输文件以及召开在线会议。它适用于多种设备,例如个人电脑、智能手机和平板电脑。 TeamViewer可以派上用场,尤其是在排除交通不便或偏远地区…

Open SUSE 安装MySQL

前言 看了一圈网上关于SUSE的教程实在是太少了,毕竟太小众了。这两天在安装MySQL的时候老是出问题,踩了一晚上的坑,发现其实很简单,网上看了方法大概有这几种 通过Yast software management安装,但是我尝试了&#x…

Linux下的基本指令(1)

嗨喽大家好呀!今天阿鑫给大家带来Linux下的基本指令(1),下面让我们一起进入Linux的学习吧! Linux下的基本指令 ls 指令pwd命令cd 指令touch指令mkdir指令(重要)rmdir指令 && rm 指令(重要)man指令(重要)cp指…

海外三大AI图片生成器对比(Stable Diffusion、Midjourney、DALL·E 3)

Stable Diffusion DreamStudio 是Stable Diffusion 的官方网页,价格便宜,对图片的操作性强,但同时编辑页面不太直观,对使用者的要求较高。 与 DALLE 和 Midjourney 不同,Stable Diffusion 是开源的。这也意味着&…

[图解]领域驱动设计伪创新-为什么互联网是重灾区-02

0 00:00:00,000 --> 00:00:04,737 我们并没有说,微信或者是美团用了领域驱动设计 1 00:00:04,737 --> 00:00:06,632 没有做这个暗示 2 00:00:06,632 --> 00:00:08,290 我只是说什么 3 00:00:09,350 --> 00:00:12,700 针对用户量很大的系统 4 00:00:…

CANoe如何实现TLS协议

TLS,Transport Layer Security,传输层安全协议。是在传输层和应用层之间,为了保证应用层数据能够安全可靠地通过传输层传输且不会泄露的安全防护。 TLS安全协议的实现逻辑,在作者本人看来,大致分为三个部分&#xff1…

minio主从同步和双机热备

文章目录 1. 安装2. 测试3. 双机热备 环境说明 服务器IPminio-slb10.10.xxx.251minio-01/02/03/0410.10.xxx.25/206/207/208minio-backup10.10.xxx.204 1. 安装 下载地址: http://dl.minio.org.cn/client/mc/release/linux-amd64/mc 安装 只有一个二进制文件&…

Spring Security OAuth2 统一登录

介绍 Spring Security OAuth2 是一个在 Spring Security 框架基础上构建的 OAuth2 授权服务器和资源服务器的扩展库。它提供了一套功能强大的工具和组件,用于实现 OAuth2 协议中的授权流程、令牌管理和访问控制。 Git地址:yunfeng-boot3-sercurity: Sp…

贴片OB2500POPA OB2500POP SOP-8 电源开关控制器IC芯片

OB2500POPA电源管理芯片被广泛应用于各种低功耗AC-DC充电器和适配器中。以下是该芯片的一些典型应用案例: 手机充电器:OB2500POPA可以用于设计高效、小巧的手机充电器,提供稳定的输出电压和电流。 USB充电器:在USB充电器中&…

第5篇:创建Nios II工程之Hello_World<四>

Q:最后我们在DE2-115开发板上演示运行Hello_World程序。 A:先烧录编译Quartus硬件工程时生成的.sof文件,在FPGA上成功配置Nios II系统;然后在Nios II Eclipse窗口右键点击工程名hello_world,选择Run As-->Nios II …

Node.js 版本升级方法

在构建vue项目时,依赖npm(Node Package Manager)工具,类似于Java项目需要maven管理。而npm是node.js的管理工具,npm依赖node.js环境才能执行。 有时候使用voscode或者其他工具安装vue项目依赖,显示一直处于…

Apollo共创生态:共筑未来智能出行新篇章

目录 引言Apollo七周年大会回顾心路历程企业生态计划 个人心得与启发技术革新的引领者展望 结语 引言 在科技飞速发展的今天,智能出行已经成为全球关注的焦点。Apollo开放平台,作为智能出行领域的先行者,已经走过了七个春秋。七年磨一剑&…
最新文章