面向数据报编程-UDP协议

news/2024/5/18 15:59:35 标签: udp, 网络协议, 网络, java-ee, java

目录

前言:

1.UDP协议API

1.1UDP编程原理

1.2DatagramSocket类

(1)DatagramSocket构造方法

(2)DatagramSocket普通方法

1.3DatagramPacket类

(1)DatagramPacket构造方法

(2)DatagramPacket普通方法

1.4InetSocketAddress类

2.代码案例

2.1服务器端

2.2客户端

2.3运行结果


前言:

网络编程-002节中已经介绍了有关传输层UDP协议的基本知识,本节不再介绍有关UDP协议的基础内容,主要讲UDP协议的重点API及其使用方法,通过案例的形式完善。

序列:网络编程 - 003


1.UDP协议API

1.1UDP编程原理

 对于UDP协议来说,具有无连接,面向数据报的特征,即每次都是没有建立连接,并且一次发送全部数据报,一次接收全部的数据报。

Java中使用UDP协议通信,主要基于DatagramSocket类来发送或接收数据报套接字,并使用DatagramPacket作为创建的UDP数据报,DatagramPacket类对象就是UDP协议中Socket的数据报。

1.2DatagramSocket类

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

(1)DatagramSocket构造方法

构造方法如下:

构造方法方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机一个随机端口(一般用于客户端)
DatagramSocket(int port)创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用于服务端)
(2)DatagramSocket普通方法

普通方法如下:

方法方法说明
void receive(DatagramPacket p)从此套接字接收数据报(如果没有接收到数据报,该方法会阻塞等待)
void send(DatagramPacket p)从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

1.3DatagramPacket类

(1)DatagramPacket构造方法

构造方法如下:

构造方法方法说明
DatagramPacket(byte[] buf , int length)构造一个DatagramPacket以用来接收数据报,接收的数据保存在字节数组(第一个参数buf)中,接收指定长度(第二个参数length)
DatagramPacket(byte[] buf , int offset , int length , SocketAddress address)构造一个DatagramPacket以用来发送数据报,发送的数据为字节数组(第一个参数buf)中,从offset到指定长度(第三个参数length)。address指定目的主机的IP和端口号

其中buf数组为输出型参数,offset默认为零,可以省略。

(2)DatagramPacket普通方法

普通方法如下:

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

1.4InetSocketAddress类

 构造UDP发送的数据报时,需要传入SocketAddress,该对象可以使用InetsocketAddress来创建。

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

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

2.代码案例

 利用传输层的UDP协议,我们可以实现一个实例。在Idea控制台手动输入字符串内容,从客户端发送给服务器端,然后服务器端不做任何处理,直接再次返回给客户端同样的字符串。

2.1服务器端

代码如下:

java">public class EchoServer {//服务器端
    //1、创建一个DatagramSocket对象
    DatagramSocket socket = null;
    public EchoServer(int port) throws SocketException {//服务器端需要自己指定端口号
        socket = new DatagramSocket(port);//这么写就是手动指定端口号
        //socket = new DatagramSocket();//这么写就是系统自动分配端口号
    }

    public void start() throws IOException {
        System.out.println("服务器启动...");
        while (true){
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            //requestPacket这个对象是用来承载数据的,在创建的时候需要创建一块内存空间来保存数据
            socket.receive(requestPacket);
            //当前完成的receive之后,数据是以二进制的形式存储到DatagramPacket中
            //还需要把这个二进制的数据转化成字符串的形式
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            //范围为0到requestPacket.getLength(),requestPacket.getLength()表示数据的真实长度
            //2、根据请求,计算响应(服务器端最核心的作用)
            String response = process(request);
            //3、把响应写回到客户端
            //搞一个响应对象,DatagramPacket
            //把DatagramPacket构造刚才的数据,再通过send返回
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(),
                    0,
                    response.getBytes().length,
                    requestPacket.getSocketAddress());//指定数据内容,同时指定数据要发给谁
            socket.send(responsePacket);
            //4、打印一个日志,把这次的数据交互的详情给打印出来
            System.out.printf("[%s:%d] req = %s,resp = %s\n",
                    responsePacket.getAddress().toString(),
                    responsePacket.getPort(),
                    request,
                    response);
        }
    }
    public String process(String request) {//请求是啥样,响应就是啥样
        //回转响应的方法
        return request;
    }
    public static void main(String[] args) throws IOException {
        EchoServer server = new EchoServer(9090);//实例测试
        server.start();
    }
}

2.2客户端

代码如下:

java">public class EchoClient {//客户端
    private DatagramSocket socket = null;
    private String serverIP = "";
    private int serverPort = 0;
    public EchoClient(String ip,int port) throws SocketException {
        //创建这个对象不能手动指定端口
        socket = new DatagramSocket();
        //由于 UDP自身不会持有对端信息,就需要在应用程序里,把对端的情况给记录下来
        //这里咱们主要记录对端的ip和端口
        serverIP = ip;
        serverPort = port;
    }
    public void start() throws IOException {
        System.out.println("客户端启动...");
        Scanner scanner = new Scanner(System.in);
        while (true){
            //1、控制台读取数据,作为请求
            System.out.println(" -> ");
            String request = scanner.next();
            //2、把请求的内容构造成DatagramSocket对象,发送给服务器
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(),
                    request.getBytes().length,
                    InetAddress.getByName(serverIP),
                    serverPort);
            socket.send(requestPacket);
            //3、尝试获取服务器响应
            DatagramPacket responsePacket = new DatagramPacket(new byte[4096],4096);
            socket.receive(responsePacket);
            //4、把响应给转换出字符串,并显示出来
            String response = new String(responsePacket.getData(),
                    0,
                    responsePacket.getLength());
            System.out.println(response);
        }
    }
    public static void main(String[] args) throws IOException {
        EchoClient client = new EchoClient("127.0.0.1",9090);
        client.start();
    }
}

2.3运行结果

在同时运行服务器端和客户端两段代码后,在客户端的控制台输入字符串,结果如图所示:

客户端:

服务器端:


以上便是对传输层的UDP协议API介绍,并举例说明了UDP协议的具体用法。


http://www.niftyadmin.cn/n/5371987.html

相关文章

从0开始图形学(光栅化)

前言 说起图形学,很多人就会提到OpenGL,但其实两者并不是同一个东西。引入了OpenGL加重了学习的难度和成本,使得一些原理并不直观。可能你知道向量,矩阵,纹理,重心坐标等概念,但就是不知道这些概…

如何在 Mac 上恢复永久删除的文件:有效方法

您是否错误地从 Mac 中删除了某个文件,并且确信它已经永远消失了?好吧,你可能错了。即使您认为已永久删除计算机上的数据,仍有可能将其恢复。 在本文中,您将了解如何在 Mac 上恢复永久删除的文件,并了解增…

django中实现数据迁移

在Django中,数据迁移(data migrations)通常指的是将模型(models)中的数据从一个状态迁移到另一个状态。这可以涉及很多操作,比如添加新字段、删除字段、更新字段的数据类型,或者更改表之间的关系…

leetcode——滑动窗口题目汇总

本章总结一下滑动窗口的解题思路: 在字符串中使用双指针 left 和 right 围成的一个左闭右开的区域作为一个窗口。不断将 right 向右滑动,直到窗口中的字符串符合条件。此时将 left 向右滑动,直到窗口中的字符串不符合条件,期间需…

【Linux】构建模块

🔥博客主页:PannLZ 🎋系列专栏:《Linux系统之路》 🥊不要让自己再留有遗憾,加油吧! 文章目录 构建第一个模块1模块的makefile2内核树内构建3内核树外构建 构建第一个模块 可以在两个地方构建模…

【Java八股面试系列】并发编程-并发关键字,线程池

目录 并发关键字 Synchronized synchronized最主要的三种使用方式: 具体使用:双重校验锁单例模式 synchronized 底层实现原理? synchronized锁的优化 偏向锁 轻量级锁 重量级锁 Mark Word 与 Monitor 之间的关系 总结 偏向锁、轻量…

3 scala集合-Set

与 Java 的 Set 一样,scala 的 set 中,元素都是唯一的,而且遍历 set 中集合的顺序,跟元素插入的顺序是不一样的。 同样,Set 也包含可变和不可变两种。要实现可变 Set 集合,需要使用类 scala.collection.mu…

eclipse4.28.0版本如何安装FatJar插件

场景: 今天准备温故下以前的老项目,于是下载了最新版本的Eclipse IDE for Enterprise Java and Web Developers - 2023-06,老项目中有些需要将程序打成jar包,于是考虑安装FatJar插件。 问题描述 一顿操作后,发现FatJar死活安装了,在线安装提示content.xml异常;离线安装…