【网络原理】使用Java基于UDP实现简单客户端与服务器通信

news2025/6/17 21:36:48

目录

  • 🎄API介绍
    • 🌸DatagramSocket
    • 🌸DatagramPacket
    • 🌸InetSocketAddress
  • 🌳回显客户端与服务器
    • 🌸建立回显服务器
    • 🌸回显客户端
  • ⭕总结

我们用Java实现UDP数据报套接字编程,需要借用以下API来实现

🎄API介绍

🌸DatagramSocket

网络编程, 本质上是要操作网卡.

但是网卡不方便直接操作. 在操作系统内核中, 使用了一种特殊的叫做 “socket” 这样的文件来抽象表示网卡.

因此进行网络通信, 势必需要先有一个 socket 对象.

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

DatagramSocket 构造方法

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

对于服务器来说, 创建 socket 对象的同时, 要让他绑定上一个具体的端口号.

服务器一定要关联上一个具体的端口的!!!

服务器是网络传输中, 被动的一方. 如果是操作系统随机分配的端口, 此时客户端就不知道这个端口是啥了, 也就无法进行通信了!!!

而做为客户端,可能客户并不知道自己那个端口什么时候空闲,如果强行指定,则可能会出现问题,所以我们选择绑定任意随机端口。

DatagramSocket ⽅法

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

🌸DatagramPacket

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

DatagramPacket 构造⽅法

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

这个就相当于你去食堂吃饭需要拿个盘子装饭一样,这个就是拿来装数据报的

DatagramSocket也提供了以下几种方法供我们使用

DatagramPacket 方法

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

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

🌸InetSocketAddress

InetSocketAddress ( SocketAddress 的⼦类 )构造⽅法:

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

🌳回显客户端与服务器

什么叫回显客户端与与服务器呢?

其实就是:客户端向服务端发送请求,一般来说我们的服务端会对我们发送的请求进行处理,我们这里为了简单,就省略里面的处理过程,只实现将请求重新发回客户端,不做任何处理。

🌸建立回显服务器

我们大致可以分为以下几步

  1. 创建一个类,为UdpEchoServer,来表示我们的UDP 版本的回显服务器
  2. 创建一个socket对象,来操作网卡
  3. 在UdpEchoServe类的构造方法里对socket对象进行构造
  4. 建立start()方法用于启动我们的服务器
  5. 由于我们的服务器需要长期开着,所以我们设计一个死循环
  6. 构造好个空白的 DatagramPacket 对象. 交给 receive 来进行填充
  7. DatagramPacket 是一个特殊的对象, 并不方便直接进行处理. 可以把这里包含的数据拿出来, 构造成一个字符串.
  8. 创建一个process()方法,这个方法就表示 “根据请求计算响应”
  9. 把响应写回到客户端. send 的参数也是 DatagramPacket. 需要把这个 Packet 对象构造好.此处构造的响应对象,
    不能是用空的字节数组构造了, 而是要使用响应数据来构造
  10. 我们加一个打印一下,当前这次请求响应的处理中间结果
  11. 最后我们创建main()函数进行启动,创建UdpEchoServer对象传入端口号,端口号为自己指定的,只要在1024 -> 65535这个范围里随便挑个数字就行了

接下来我们一起来看看代码的实现:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

// UDP 版本的回显服务器
public class UdpEchoServer {
    // 网络编程, 本质上是要操作网卡.
    // 但是网卡不方便直接操作. 在操作系统内核中, 使用了一种特殊的叫做 "socket" 这样的文件来抽象表示网卡.
    // 因此进行网络通信, 势必需要先有一个 socket 对象.
    private DatagramSocket socket = null;

    // 对于服务器来说, 创建 socket 对象的同时, 要让他绑定上一个具体的端口号.
    // 服务器一定要关联上一个具体的端口的!!!
    // 服务器是网络传输中, 被动的一方. 如果是操作系统随机分配的端口, 此时客户端就不知道这个端口是啥了, 也就无法进行通信了!!!
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        // 服务器不是只给一个客户端提供服务就完了. 需要服务很多客户端.
        while (true) {
            // 只要有客户端过来, 就可以提供服务.
            // 1. 读取客户端发来的请求是啥.
            //    receive 方法的参数是一个输出型参数, 需要先构造好个空白的 DatagramPacket 对象. 交给 receive 来进行填充.
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);
            socket.receive(requestPacket);
            // 此时这个 DatagramPacket 是一个特殊的对象, 并不方便直接进行处理. 可以把这里包含的数据拿出来, 构造成一个字符串.
            String request = new String(requestPacket.getData(), 0, requestPacket.getLength());
            // 2. 根据请求计算响应, 由于此处是回显服务器, 响应和请求相同.
            String response = process(request);
            // 3. 把响应写回到客户端. send 的参数也是 DatagramPacket. 需要把这个 Packet 对象构造好.
            //    此处构造的响应对象, 不能是用空的字节数组构造了, 而是要使用响应数据来构造.
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            // 4. 打印一下, 当前这次请求响应的处理中间结果.
            System.out.printf("[%s:%d] req: %s; resp: %s\n", requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request, response);
        }
    }

    // 这个方法就表示 "根据请求计算响应"
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        // 端口号的指定, 大家可以随便指定.
        // 1024 -> 65535 这个范围里随便挑个数字就行了.
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}

🌸回显客户端

我们分为以下几步:

  1. 我们创建一个类UdpEchoClient来表示客户端服务。
  2. 创建socket对象,来操作网卡
  3. 定义两个变量,一个表示服务器的IP地址,一个表示端口号
  4. 在UdpEchoClient的构造方法里进行构造
  5. 构造成 UDP 请求, 并发送,构造这个 Packet 的时候, 需要把 serverIp 和 port 都传入过来. 但是此处 IP地址需要填写的是一个 32位的整数形式.上述的 IP 地址是一个字符串. 需要使用InetAddress.getByName来进行一个转换.
  6. 读取服务器的 UDP 响应, 并解析,构造好个空白的 DatagramPacket 对象. 交给 receive 来进行填充
  7. 把解析好的结果显示出来.
  8. 创建main函数,创造UdpEchoClient对象,并把服务器的IP和端口给传进去
  9. 启动服务器

代码实现如下:

import java.io.IOException;
import java.net.*;
import java.util.Scanner;

// UDP 版本的 回显客户端
public class UdpEchoClient {
    private DatagramSocket socket = null;
    private String serverIp = null;
    private int serverPort = 0;

    // 一次通信, 需要有两个 ip, 两个端口.
    // 客户端的 ip127.0.0.1 已知.
    // 客户端的 port 是系统自动分配的.
    // 服务器 ip 和 端口 也需要告诉客户端. 才能顺利把消息发个服务器.
    public UdpEchoClient(String serverIp, int serverPort) throws SocketException {
        socket = new DatagramSocket();
        this.serverIp = serverIp;
        this.serverPort = serverPort;
    }

    public void start() throws IOException {
        System.out.println("客户端启动!");
        Scanner scanner = new Scanner(System.in);
        while (true) {
            // 1. 从控制台读取要发送的数据
            System.out.print("> ");
            String request = scanner.next();
            if (request.equals("exit")) {
                System.out.println("goodbye");
                break;
            }
            // 2. 构造成 UDP 请求, 并发送
            //    构造这个 Packet 的时候, 需要把 serverIp 和 port 都传入过来. 但是此处 IP 地址需要填写的是一个 32位的整数形式.
            //    上述的 IP 地址是一个字符串. 需要使用 InetAddress.getByName 来进行一个转换.
            DatagramPacket requestPacket = new DatagramPacket(request.getBytes(), request.getBytes().length,
                    InetAddress.getByName(serverIp), serverPort);
            socket.send(requestPacket);
            // 3. 读取服务器的 UDP 响应, 并解析
            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", 9090);
        client.start();
    }
}

客户端
在这里插入图片描述
服务端
在这里插入图片描述

⭕总结

关于《【网络原理】使用Java基于UDP实现简单客户端与服务器通信》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!

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

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

相关文章

深度学习相关概念及术语总结

目录 1.CNN2.RNN3.LSTM4.NLP5.CV6.正向传播7.反向传播8.sigmoid 函数9.ReLU函数10.假设函数11.损失函数12.代价函数 1.CNN CNN 是卷积神经网络(Convolutional Neural Network)的缩写。卷积神经网络是一种深度学习模型,专门用于处理具有网格状…

数据可视化基础篇-图形语法

当我们在制作仪表盘或其他数据可视化时离不开对图表的选择,不同的数据信息该怎么选择图表可能是不少人会遇到的问题。 要解决这个问题我们首先需要理解数据可视化的生成规律或者说是“语法”,目前主流的数据可视化理论认为,可视化是由基础标…

存储引擎的简介

简介: 1.在mysql存储引擎可以说就是指表的类型,可以称为表处理器,以表的形式存储。 2.他的功能就是接收上层传下来的指令,然后对表中的数据进行提取写入操作。 目的: 为了管理方便,我们把连接管理&#xf…

生成对抗网络 (GAN)

生成对抗网络(Generative Adversarial Networks,GAN)是由Ian Goodfellow等人在2014年提出的一种深度学习模型。GAN由两部分组成:一个生成器(Generator)和一个判别器(Discriminator)&…

代码随想录算法训练营第四天|24.两两交换链表中的节点、19.删除链表的倒数第N的节点、07.链表相交、142.环形链表II

代码随想录算法训练营第四天|24.两两交换链表中的节点、19.删除链表的倒数第N的节点、07.链表相交、142.环形链表II 24.两两交换链表中的节点 给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成…

创建数据表

Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 如果要进行数据表的创建 create table 表名称 (列名称 类型 [DEFAULT 默认值 ] ,列名称 类型 [DEFAULT 默认值 ] ,列名称 类型 [DEFAULT 默认值 ] ,...列名称 类型 [DEFAULT 默认值 ] )…

JS直接量及其相关对象

什么是直接量 直接量是指不需要创建对象就可以直接使用的变量。ES中的直接量主要有三种类型:表示字符串的string类型、表示数字的number类型和表示true/false的boolean类型。当我们直接将值赋给变量后,ES就会自动判断其类型,而且当参数发生变…

springboot + jpa + 达梦数据库兼容 Mysql的GenerationType.IDENTITY主键生成策略

导入达梦数据库对hibernate的方言包 <dependency><groupId>com.dameng</groupId><artifactId>DmDialect-for-hibernate5.6</artifactId><version>8.1.2.192</version></dependency>配置文件中添加方言配置和主键生成策略配置…

如何在一个pycharm项目中创建jupyter notebook文件,并切换到conda环境中

1、第一步可以直接在pycharm项目中创建jupyter notebook文件 2、假若想要切换成pytorch环境做实验例子&#xff0c;会发现报这个错误 Jupyter server process exited with code 1 C:\Users\12430\.conda\envs\pytorch3.11\python.exe: No module named jupyter在这里&#xff…

洞悉 Kubernetes 高阶奥秘:掌控资源、网络、存储,玩转容器化应用!

昨天我们已经入门了K8S&#xff0c;今天带大家学习一下资源、网络、存储这几个进阶的知识点模块内容。这几天陆陆续续会把K8S从头到尾讲一遍&#xff0c;最后会带大家实战一下&#xff0c;下面就开始今天的学习吧。 高级资源和控制器 Kubernetes 提供了一系列高级资源和控制器…

Toyota Programming Contest 2024#3(AtCoder Beginner Contest 344)(A~C)

A - Spoiler 竖线里面的不要输出&#xff0c;竖线只有一对&#xff0c;且出现一次。 #include <bits/stdc.h> //#define int long long #define per(i,j,k) for(int (i)(j);(i)<(k);(i)) #define rep(i,j,k) for(int (i)(j);(i)>(k);--(i)) #define debug(a) cou…

【自动化】PyoutuGUI操作键鼠

自动化之PyoutuGUI操作键鼠 文章目录 自动化之PyoutuGUI操作键鼠  &#x1f449;引言&#x1f48e;一、初始化环境二、键盘鼠标事件三、消息框功能四、案例实战自动登录WPS 五、问题解决 &#x1f449;引言&#x1f48e; 学习的最大理由是想摆脱平庸&#xff0c;早一天就多一…

CSS基础知识

font-family: "Trebuchet MS", Verdana, sans-serif; 字体栈&#xff0c;浏览器会一个一个试过去看下哪个可以用 font-size16px; font-size1em; font-size100%;//相对于16px 字体大小&#xff0c;需要进行单位换算16px1em font-weightnormal;//400font-weight属性…

STM32CubeMX学习笔记17--- FSMC

1.1 TFTLCD简介 TFT-LCD&#xff08;thin film transistor-liquid crystal display&#xff09;即薄膜晶体管液晶显示器。液晶显示屏的每一个像素上都设置有一个薄膜晶体管&#xff08;TFT&#xff09;&#xff0c;每个像素都可以通过点脉冲直接控制&#xff0c;因而每个节点都…

2024年3月10日 十二生肖 今日运势

小运播报&#xff1a;2024年3月10日&#xff0c;星期日&#xff0c;农历二月初一 &#xff08;甲辰年丁卯月癸酉日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;龙、牛、蛇 需要注意&#xff1a;鸡、狗、兔 喜神方位&#xff1a;东南方 财神方位&#xff1a;…

Linux——文件重定向

目录 前言 一、重定向 二、重定向的运用 三、dup2 四、命令行中的重定向 五、为什么要有标准错误 前言 在之前我们学习了文件标识符&#xff0c;直到close可以使用文件标识符进行关闭&#xff0c;但是当我们关闭1号&#xff08;stdout&#xff09;时&#xff0c;无法往显…

基于springboot实现图书推荐系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现图书馆推荐系统演示 摘要 时代的变化速度实在超出人类的所料&#xff0c;21世纪&#xff0c;计算机已经发展到各行各业&#xff0c;各个地区&#xff0c;它的载体媒介-计算机&#xff0c;大众称之为的电脑&#xff0c;是一种特高速的科学仪器&#xff0c;比…

软件测试自学和报班学习的区别,各有各的优势和缺点,大家看完之后自己选择喔

时代在进步&#xff0c;人们汲取知识的方式不再是单一的在书本上面&#xff0c;现在网络发达&#xff0c;只需要上网就能找到相关的好多知识&#xff0c;慢慢的大家越来越觉得有了这些知识&#xff0c;只要自己有自制力就完全能够自学到一定的程度。 在自学氛围的影响下&#…

深度学习+感知机

深度学习感知机 1感知机总结 2多层感知机1XOR2激活函数3多类分类总结 3代码实现 1感知机 是个很简单的模型,是个二分类的问题。 感知机&#xff08;perceptron&#xff09;是Frank Rosenblatt在1957年提出的一种人工神经网络&#xff0c;被视为一种最简单形式的前馈神经网络&…

could not publish server configuration for tomcat at localhost

1&#xff0c;报错信息如图&#xff1a; 2&#xff0c;找到servers双击&#xff0c;选择Modules&#xff0c;如果有两个webModules ,remove一个&#xff0c; 3&#xff0c;如果重启还是报错&#xff0c;干脆两个都remove&#xff0c;双击tomcat服务add And Remove重新添加