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

目录

  • 🎄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.mzph.cn/news/732664.shtml

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

相关文章

yolo模型中神经节点Mul与Sigmoid 和 Conv、Concat、Add、Resize、Reshape、Transpose、Split

yolo模型中神经节点Mul与Sigmoid 和 Conv、Concat、Add、Resize、Reshape、Transpose、Split 在YOLO(You Only Look Once)模型中,具体作用和用途的解释:

Claude 3 Sonnet 模型现已在亚马逊云科技的 Amazon Bedrock 正式可用!

今天,我们宣布一个激动人心的里程碑:Anthropic 的 Claude 3 Sonnet 模型现已在亚马逊云科技的 Amazon Bedrock 正式可用。 下一代 Claude (Claude 3) 的三个模型 Claude 3 Opus、Claude 3 Sonnet 和 Claude 3 Haiku 将陆续登陆 Amazon Bedrock。Amazon …

二叉树遍历(前中后序的递归/非递归遍历、层序遍历)

二叉树的遍历 1. 二叉树的前序、中序、后序遍历 前、中、后序遍历又叫深度优先遍历 注:严格来说,深度优先遍历是先访问当前节点再继续递归访问,因此,只有前序遍历是严格意义上的深度优先遍历 首先需要知道下面几点: …

【排序】详解插入排序

一、思想 插入排序是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。具体步骤如下,将数组下标为0的元素视为已经排序的部分,从1开始遍历数组,在遍历的过程中当前元素从…

upload-labs通关记录

文章目录 前言 1.pass-012.pass-023.pass-034.pass-045.pass-056.pass-067.pass-078.pass-089.pass-0910.pass-1011.pass-1112.pass-1213.pass-1314.pass-1415.pass-1516.pass-1617.pass-1718.pass-1819.pass-19 前言 本篇文章记录upload-labs中,所有的通过技巧和各…

蓝桥杯python常用内置函数

一、 abs() #返回数字的绝对值 例: 二、 all() #判断给定的可迭代参数中的所有元素是否都为True,若是则返回True,反之返回False 例: 三、 any() #判断给定的可迭代参数是否都为False,全为False则返回False&am…

SSL 证书,了解一下常识

公司的网站、应用怎么才能保证在互联网上安全运行,不被攻击、盗取数据呢? 创业必经之路,一步一步走就对了,可能没赶上红利期,但不做就等于0。 概述 SSL 证书(SSL Certificates)又称数字证书&am…

leetcode 1143. 最长公共子序列【动态规划】

leetcode 1143. 最长公共子序列 int longestCommonSubsequence(char* text1, char* text2) {int len1 strlen(text1);int len2 strlen(text2);int dp[len1 1][len2 1];memset(dp, 0, sizeof(dp));for (int i 1; i < len1; i) {for (int j 1; j < len2; j) {if (t…

【vue2基础教程】vue指令

文章目录 前言一、内容渲染指令1.1 v-text1.2 v-html1.3 v-show1.4 v-if1.5 v-else 与 v-else-if 二、事件绑定指令三、属性绑定指令总结 前言 Vue.js 是一款流行的 JavaScript 框架&#xff0c;广泛应用于构建交互性强、响应速度快的现代 Web 应用程序。Vue 指令是 Vue.js 中…

IPsec VPN之安全联盟

一、何为安全联盟 IPsec在两个端点建立安全通信&#xff0c;此时这两个端点被称为IPsec对等体。安全联盟&#xff0c;即SA&#xff0c;是指通信对等体之间对某些要素的约定&#xff0c;定义了两个对等体之间要用何种安全协议、IP报文的封装方式、加密和验证算法。SA是IPsec的基…

使用jar命令删除.jar文件中的重复的类和目录并重新打包

引言&#xff1a; android项目&#xff0c;引入的 .jar包 和 .aar中 有相同的类&#xff0c;导致编译冲突&#xff0c;由于这些依赖项没有上传到Maven仓库&#xff0c;无法使用 exclude 排除&#xff0c;只能尝试修改jar文件&#xff0c;删除重复的代码&#xff0c;再重新打包…

CACLP预告 | 飞凌嵌入式与您相约山城重庆

第二十一届中国国际检验医学暨输血仪器试剂博览会&#xff08;CACLP&#xff09;将于2024年3月16日-18日在重庆国际博览中心举行。本次会议将探讨科技创新趋势&#xff0c;展示最新成果&#xff0c;发现和挖掘颠覆性技术和创新产品&#xff0c;引领实验医学体外诊断科技创新和未…

电脑资料管理软件(5个高效批量管理电脑资料的方法)

企业电脑资料管理是企业一大难题&#xff0c;为什么这样说&#xff1f; 首先&#xff0c;企业电脑资料的数量庞大且种类繁多。 其次&#xff0c;电脑资料的安全性和保密性要求高。 再者&#xff0c;电脑资料的管理涉及到多个部门和员工的协作。 ...... 针对此类情况很多企业…

CODESYS双通气缸功能块(ST源代码)

博途PLC双通气缸功能块请参考下面文章链接: https://rxxw-control.blog.csdn.net/article/details/136415539https://rxxw-control.blog.csdn.net/article/details/136415539CODESYS 结构变量使用 https://rxxw-control.blog.csdn.net/article/details/126248829

【Python】Python Astar算法生成最短路径GPS轨迹

简介 最短路径问题是计算机科学中一个经典问题&#xff0c;它涉及找到图中两点之间距离最短的路徑。在实际应用中&#xff0c;最短路径算法用于解决广泛的问题&#xff0c;例如导航、物流和网络优化。 步骤 1&#xff1a;加载道路网络数据 要计算最短路径&#xff0c;我们需…

JetPack入门

先导入依赖 implementation("androidx.lifecycle:lifecycle-extensions:2.2.0") 1.使用LifeCycle解耦页面与组件 Activity package com.tiger.lifecycle;import android.annotation.SuppressLint; import android.os.Bundle; import android.os.SystemClock; impo…

[Python人工智能] 四十二.命名实体识别 (3)基于Bert+BiLSTM-CRF的中文实体识别万字详解(异常解决中)

从本专栏开始,作者正式研究Python深度学习、神经网络及人工智能相关知识。前文讲解如何实现中文命名实体识别研究,构建BiGRU-CRF模型实现。这篇文章将继续以中文语料为主,介绍融合Bert的实体识别研究,使用bert4keras和kears包来构建Bert+BiLSTM-CRF模型。然而,该代码最终结…

【Haproxy】Haproxy的配置和应用

HAProxy介绍 HAProxy是法国开发者威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件&#xff0c;是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器&#xff0c;支持基于cookie的持久性&#xff0c;自动故障切换&#xff0c;支持正则表达式及web状态统计&a…

[eslint error] ‘v-model‘ should be on a new line.

错误详情 错误原因 此问题是由于.eslintrc.js文件中的vue/max-attributes-per-line配置错误产生的 esline默认要求属性单独开一行 错误解决 所以解决的方法有两个一个是遵从eslint默认规则让属性新开一行,能解决问题 但是我不喜欢看这样子的代码,所以我只好去改掉eslint的规…

什么是数据采集与监视控制系统(SCADA)?

SCADA数据采集是一种用于监控和控制工业过程的系统。它可以实时从现场设备获得数据并将其传输到中央计算机&#xff0c;以便进行监控和控制。SCADA数据采集系统通常使用传感器、仪表和控制器收集各种类型的数据&#xff0c;例如温度、压力、流量等&#xff0c;然后将这些数据汇…