【网络通信】探索TCP通信与UDP通信的奥妙

🌺个人主页:Dawn黎明开始

🎀系列专栏:Java
每日一句:知不足而奋进,望远山而前行

📢欢迎大家:关注🔍+点赞👍+评论📝+收藏⭐️


文章目录

一.🔐TCP通信

1.1🔓 ServerSocket类

1.1.1🔑构造方法

1.1.2🔑常用方法

1.2🔓Socket类

1.2.1🔑 构造方法

1.2.2🔑常用方法

1.3🔓简单的TCP通信

1.4🔓多线程的TCP网络程序

二.🔐UDP通信

2.1🔑DatagramPacket类

2.1.1🔑构造函数

2.1.2🔑常用方法

2.2🔑DatagramSocket类

2.2.1🔑构造方法

2.2.2🔑常用方法

2.3🔓简单的UDP通信

2.3.1🔑UDP通信中数据报的发送过程

2.3.2🔑UDP通信中数据报的接收过程

2.3.3🔑UDP通信案例

2.3.4🔑注意事项

2.4🔓多线程的UDP网络程序

📝全文总结


一.🔐TCP通信

1.1🔓 ServerSocket类

    在Socket编程中,编写服务器端程序需要使用ServerSocket类。ServerSocket类在java.net包中,java.net. ServerSocket继承自java.lang.Object类。ServerSocket类的主要作用是接收客户端的连接请求

1.1.1🔑构造方法

1.1.2🔑常用方法

     了解了ServerSocket类的构造方法后,下面学习一下ServerSocket类的常用方法

1.2🔓Socket类

     Socket类在java.net包中定义,java.net.Socket继承自java.lang.Object类。Socket类用于编写客户端程序,用户通过创建一个Socket对象建立与服务器的连接。

1.2.1🔑 构造方法

1.2.2🔑常用方法

1.3🔓简单的TCP通信

    下面通过一个TCP通信的案例进一步学习ServerSocket类和Socket类的用法。要实现TCP通信需要创建一个服务器端程序和一个客户端程序。具体步骤如下。

步骤一首先实现服务器端程序

代码如下👇🏻

 public class TCPServer {public static void main(String[] args) throws Exception {Socket client = null;                             //声明Socket对象OutputStream os = null;                      //声明OutputStream对象//创建ServerSocket对象并指定端口号(7788)ServerSocket serverSocket = new ServerSocket(7788); System.out.println("服务器正在运行,等待与客户端连接");client = serverSocket.accept();             //程序阻塞,等待客户端连接os = client.getOutputStream();            //获取客户端的输出流System.out.println("开始与客户端交互数据");// 当客户端连接到服务器端时,向客户端输出数据os.write(("北京欢迎你!").getBytes());Thread.sleep(5000);                           //模拟执行其他功能占用的时间System.out.println("结束与客户端交互数据");os.close();client.close();}}

运行结果👇🏻

      从图的运行结果可以看出,控制台打印出了“服务器正在运行,等待与客户端连接”,并且控制台中的光标一直在闪动,这是因为accept()方法在执行时发生阻塞,直到客户端连接之后才会结束这种阻塞状态。

步骤二接下来编写客户端程序,并介绍如何通过客户端访问服务器端。

代码如下👇🏻

public class TCPClient {public static void main(String[] args) throws Exception {Socket client = null;                               //声明Socket对象client = new Socket("localhost",7788);  //指定连接的主机端口号BufferedReader buf = null;  //声明BufferedReader对象,用于接收信息buf = new BufferedReader(new InputStreamReader(client.getInputStream()              //取得客户端的输入流));String str = buf.readLine();                        //读取信息System.out.println("服务器端输出内容:"+str);client.close();                                        //关闭Socketbuf.close();                                            //关闭输入流}
}

运行结果👇🏻

服务器端控制台变化

      在客户端创建的Socket对象成功读取服务器端发来的数据并打印在控制台后,同时服务器端程序会结束阻塞状态,并在控制台中打印出“开始与客户端交互数据”,然后向客户端发送数据“北京欢迎你!”,在服务器端休眠5秒钟后会在控制台打印出“结束与客户端交互数据”,本次通信才结束。如下图所示👇🏻

1.4🔓多线程的TCP网络程序

       案例演示多线程的TCP网络程序

步骤一使用多线程的方式编写了一个服务器端程序。通过在while循环中调用accept()方法不停的接收客户端发送的请求。

代码如下👇🏻

public class TCPServer {public static void main(String[] args) throws Exception {// 创建ServerSocket对象,监听指定的端口ServerSocket serverSocket = new ServerSocket(7788);// 使用while循环不停的接收客户端发送的请求while (true) {// 调用ServerSocket的accept()方法等待客户端的连接final Socket client = serverSocket.accept();int port = client.getPort();//获取Socket对象与服务器端连接的端口号System.out.println("与端口号为"+port+"的客户端连接成功!"); // 下面的代码在步骤二中完成,开启一个新的线程处理客户端发送的数据}}
}

步骤二创建一个线程并开启,处理客户端发送的数据。

代码如下👇🏻

            new Thread() {public void run() {OutputStream os= null;  	             // 定义一个输出流对象try {os = client.getOutputStream(); // 获取客户端的输出流System.out.println("开始与客户端交互数据");os.write(("北京欢迎你!").getBytes());Thread.sleep(5000);              // 使线程休眠5000毫秒System.out.println("结束与客户端交互数据");os.close();                        // 关闭输出流client.close();                   // 关闭Socket对象} catch (Exception e) {e.printStackTrace();}};}.start();

步骤三为了验证服务器端程序是否实现了多线程,这里需要再创建两个与13.2.3节中相同的客户端程序,只需修改其类名即可。客户端程序创建完成之后,首先运行本节中的服务器端程序,之后连续运行3个客户端程序。

测试过程

        在测试过程中,当运行第一个客户端程序时,服务器端马上就进行数据处理,打印出“与端口号为60351的客户端连接成功!”的信息(端口是随机的,可能不同),紧接着再运行第2个和第3个客户端程序,会发现服务端也立刻做出回应,同时启动的这3个客户端都能够接收到服务端响应的信息。

运行结果👇🏻

     由图可知,通过多线程的方式,可以实现多个客户端程序对同一个服务器端程序的访问。

二.🔐UDP通信

2.1🔑DatagramPacket类

    DatagramPacket类用于封装UDP通信中发送或者接收的数据,DatagramPacket类对象也称为数据报对象。利用UDP通信时,发送端使用DatagramPacket类将数据打包,即用DatagramPacket类创建一个数据报对象,这个数据报对象包含有需要传输的数据数据报的长度IP地址端口号等信息。

2.1.1🔑构造函数

    想要创建一个DatagramPacket对象,首先需要了解一下它的构造方法。在创建发送端和接收端的DatagramPacket对象时,使用的构造方法有所不同,接收端的构造方法只需要接收一个字节数组作为参数,用于存放接收到的数据;而发送端的构造方法不但要接收存放了发送数据的字节数组,还需要指定发送端IP地址和端口号

2.1.2🔑常用方法

2.2🔑DatagramSocket类

    DatagramSocket类用于在发送主机中建立数据报通信方式,提出发送请求,实现数据报的发送与接收。在创建发送端接收端的DatagramSocket对象时,使用的构造方法也有所不同。

2.2.1🔑构造方法

2.2.2🔑常用方法

UDP连接注意事项

     由于UDP连接是不可靠的通信方式,所以调用receive()方法时不一定能接收到数据,为了防止线程死掉,应该调用setSoTimeout()方法设置超时参数timeout()。另外,receive()方法和send()方法都可能产生输入、输出异常,因此都可能抛出IOException异常

2.3🔓简单的UDP通信

2.3.1🔑UDP通信中数据报的发送过程

(1)创建一个用于发送数据报的DatagramPacket对象,使其包含如下信息:

1.要发送的数据

2.数据报分组的长度

3.发送目的地的主机IP地址和目的端口号

(2)在指定的或可用的本机端口创建DatagramSocket对象。

(3)调用DatagramSocket对象的send()方法,以DatagramPacket对象为参数发送数据报。

2.3.2🔑UDP通信中数据报的接收过程

(1)创建一个用于接收数据报的DatagramSocket对象,其中包含空白数据缓冲区和指定数据报分组的长度。

(2)在指定的或可用的本机端口创建DatagramSocket对象。

(3)调用DatagramSocket对象的receive()方法,以DatagramPacket对象为参数接收数据报,接收到的信息有:

1.收到的数据报分组。

2.发送端主机的IP地址。

3.发送端主机的发送端口号。

2.3.3🔑UDP通信案例

     要实现UDP通信需要创建一个发送端程序和一个接收端程序。在通信时只有接收端程序先运行,才能避免发送端发送数据时找不到接收端而造成数据丢失的问题。因此,首先需要完成接收端程序的编写,然后完成发送端程序的编写。

步骤一首先需要完成接收端程序的编写。

代码如下👇🏻

public class Receiver {public static void main(String[] args) throws Exception {byte[] buf = new byte[1024]; // 创建一个字节数组,用于接收数据// 定义一个DatagramSocket对象,端口号为8954DatagramSocket ds = new DatagramSocket(8954);// 定义一个DatagramPacket对象,用于接收数据DatagramPacket dp = new DatagramPacket(buf, buf.length);System.out.println("等待接收数据");ds.receive(dp);                 	 // 接收数据/*调用DatagramPacket的方法获得接收到的信息包括数据的内容、长    度、发送的IP地址和端口号*/String str = new String(dp.getData(), 0, dp.getLength()) +" from "+ dp.getAddress().getHostAddress() + ":" + dp.getPort();System.out.println(str); 		 // 打印接收到的信息ds.close();                 		 // 关闭数据报连接}
}

接收端程序运行结果👇🏻

    从图可以看出,接收端程序运行后,程序一直处于阻塞状态,这是因为DatagramSocket的receive()方法在等待接收发送端发送过来的数据,只有接收到发送端发送的数据,该方法才会结束这种阻塞状态,程序才能继续向下执行。

步骤二实现了接收端程序之后,接下来编写发送端程序,用于给接收端发送数据。

代码如下👇🏻

public class Sender {public static void main(String[] args) throws Exception {// 创建一个DatagramSocket对象DatagramSocket ds = new DatagramSocket(3000);String str = "hello world"; //要发送的数据byte[] arr = str.getBytes(); //将定义的字符串转为字节数组/*创建一个要发送的数据报,数据报包括发送的数据,数据的长度,接收端的IP地址以及端口号*/DatagramPacket dp = new DatagramPacket(arr, arr.length,InetAddress.getByName("localhost"), 8954);System.out.println("发送信息");ds.send(dp); // 发送数据ds.close();  	// 释放资源}
}

 发送端程序运行结果👇🏻

接收端控制台变化

       运行发送端程序后,接收端程序就会收到发送端发送的数据而结束阻塞状态,并打印接收的数据。

 2.3.4🔑注意事项

UDP程序所使用的端口号被占用时发生运行异常

      需要注意的是,当UDP程序所使用的端口号被占用时,程序会抛出异常

运行结果👇🏻

      出现图中所示的情况,是因为在一台计算机中,一个端口号只能被一个应用程序占用,当我们编写的UDP程序所使用的端口号已经被其他的应用程序占用时,就会出现这种情况。遇到这种情况时,可以在命令行窗口输入netstat -ano命令来查看当前计算机端口的占用情况。

netstat -ano命令运行结果👇🏻

       如上图所示,显示了所有正在运行的应用程序及它们所占用的端口号。想要解决端口号占用的问题,只需关掉占用端口号的应用程序或者使用一个未被占用的端口号重新运行程序即可。

2.4🔓多线程的UDP网络程序

       接下来通过一个案例演示使用UDP通信方式实现多线程的UDP网络程序,具体步骤如下👇🏻

步骤一创建接收端程序Receive类继承Thread类。

代码如下👇🏻

class Receive extends Thread {public void run() {try {//创建socket相当于创建码头DatagramSocket socket = new DatagramSocket(6666);//创建packet相当于创建集装箱DatagramPacket packet = new DatagramPacket(new byte[1024], 1024);while(true) {socket.receive(packet);//接收货物byte[] arr = packet.getData();int len = packet.getLength();String ip = packet.getAddress().getHostAddress();System.out.println(ip + ":" + new String(arr,0,len));}} catch (IOException e) {e.printStackTrace();}}
}

步骤二创建发送端程序Send类继承Thread类。

代码如下👇🏻

class Send extends Thread {public void run() {try {DatagramSocket socket = new DatagramSocket();//创建socket相当于创建码头Scanner sc = new Scanner(System.in);while(true) {String str = sc.nextLine();if("quit".equals(str))break;DatagramPacket packet = new DatagramPacket(str.getBytes(),str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);socket.send(packet);//发货}socket.close();}  catch (IOException e) {e.printStackTrace();}}
}

运行结果👇🏻

📝全文总结

      本文主要讲解了TCP程序设计中相关的ServerSocket类Socket类,并通过两个案例实现了简单的TCP通信和多线程的TCP通信;最后介绍了UDP程序设计相关的DatagramPacket类DatagramSocket类,并通过两个的案例实现了简单的UDP通信和多线程的UDP通信。通过对本文的学习,希望大家能够对网络编程的底层原理有一个简单的了解,为以后的网络编程开发打下基础。


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

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

相关文章

QQ微云在哪里打开?答案在这,记得收藏!

QQ微云是腾讯推出的一项智能云服务,它可以帮助大家储存照片、视频、文档等重要文件,以防数据丢失。用户们可以免费使用QQ微云,并且可以随时随地上传或下载自己的文件。那么,qq微云在哪里打开?今天,就让我们…

Python 装饰器用法详解

目录 一、基本概念 二、语法形式 三、用法示例 1、用于日志记录 2、用于性能测试 3、用于事务处理 4、用于缓存结果 5、用于权限验证 总结 Python装饰器是Python中一种非常有用且强大的工具,它允许我们在不修改原有函数或类的基础上,对它们进行…

SOLIDWORKS实用技巧——工程图模板替换

概述 工程师常在出图时选择最佳模板,在编辑一段时间后,发现需要更改图纸大小,怎样更改图纸大小还不影响现有工作。你是否也有此类问题? 那么,新建工程图时的模板从哪里来?如何轻松替换已有工程图的图纸格…

IDEA-SVN合并分支到主干

IDEA-SVN合并branch分支到主干master 1.选择VCS的 Integrate Project 2.选择分支合并 Source1 是合并后的分支 , 主分支 master Source2 是被合并的分支 , 分支 branch Try merge 可以尝试是否可以能够被合并,并且无冲突 3.合并完成后当前项目会出现需要提交的内容,检查一…

CSS特效014: hover后左右开门的效果

CSS常用示例100专栏目录 本专栏记录的是经常使用的CSS示例与技巧,主要包含CSS布局,CSS特效,CSS花边信息三部分内容。其中CSS布局主要是列出一些常用的CSS布局信息点,CSS特效主要是一些动画示例,CSS花边是描述了一些CSS…

汽车级芯片NCV7518MWATXG 可编程六沟道低压侧 MOSFET预驱动器 特点、参数及应用

NCV7518MWATXG 可编程六沟道低压侧 MOSFET 预驱动器属于 FLEXMOS™ 汽车级产品,用于驱动逻辑电平 MOSFET。该产品可通过串行 SPI 和并行输入组合控制。该器件提供 3.3 V/5 V 兼容输入,并且串行输出驱动器可以采用 3.3 V 或 5 V 供电。内部通电重置提供受…

做进销存什么软件好用

进销存软件是企业管理库存、采购和销售等环节的信息化管理系统,对于企业的运营和管理具有重要的意义。在选择进销存软件时,需要考虑以下因素: 功能需求:选择能够满足企业实际需求的进销存软件。例如,系统是否支持商品…

边缘计算系统设计与实践

💂 个人网站:【 海拥】【神级代码资源网站】【办公神器】🤟 基于Web端打造的:👉轻量化工具创作平台💅 想寻找共同学习交流的小伙伴,请点击【全栈技术交流群】 随着物联网、大数据和人工智能等技术的快速发展…

使用低代码可视化开发平台快速搭建应用

目录 一、JNPF可视化平台介绍 二、搭建JNPF可视化平台 【表单设计】 【报表设计】 【流程设计】 【代码生成器】 三、使用JNPF可视化平台 1.前后端分离: 2.多数据源: 3.预置功能: 4.私有化部署: 四、总结 可视化低代码…

【云原生】Spring Cloud Alibaba 之 Gateway 服务网关实战开发

目录 一、什么是网关 ⛅网关的实现原理 二、Gateway 与 Zuul 的区别? 三、Gateway 服务网关 快速入门 ⛄需求 ⏳项目搭建 ✅启动测试 四、Gateway 断言工厂 五、Gateway 过滤器 ⛽过滤器工厂 ♨️全局过滤器 六、源码地址 ⛵小结 一、什么是网关 Spri…

打包项目报错:程序包javax.servlet不存在

背景: WebService项目在没有配置Tomcat的情况下重新打包,由于是直接导入别人写好的项目,没有配置其他环境,所以报错程序包javax.servlet不存在 解决方法: 找到servlet-api.jar包,导入到现有项目的SDK 重…

Java,数据结构与集合源码,数据结构概述

目录 数据结构概念: 数据结构的研究对象: 研究对象一,数据间逻辑关系: 研究对象二,数据的存储结构(或物理结构): 研究对象三:运算结构 数据结构的相关介绍&#xff…

BGP的基础知识

BGP——边界网关协议 IGP——内部网关协议——OSPF、RIP、ISIS EGP——外部网关协议——EGP、BGP 边界网关协议BGP是一种实现自治系统AS之间的路由可达,并选择最佳路由的路径矢量路由协议。目前在IPV4环境下主要使用BGPV4,目前市场上也存在BGPV4&…

使用ExLlamaV2量化并运行EXL2模型

量化大型语言模型(llm)是减少这些模型大小和加快推理速度的最流行的方法。在这些技术中,GPTQ在gpu上提供了惊人的性能。与非量化模型相比,该方法使用的VRAM几乎减少了3倍,同时提供了相似的精度水平和更快的生成速度。 ExLlamaV2是一个旨在从…

SpringBoot : ch04 整合数据源

前言 Spring Boot 是当今最流行的 Java 开发框架之一,它以简洁、高效的特点帮助开发者快速构建稳健的应用程序。在实际项目中,涉及到数据库操作的需求时,我们需要对数据源进行整合。本文将重点介绍如何在 Spring Boot 中整合数据源&#xff…

NX二次开发UF_CAM_PREF_ask_integer_value 函数介绍

文章作者:里海 来源网站:https://blog.csdn.net/WangPaiFeiXingYuan UF_CAM_PREF_ask_integer_value Defined in: uf_cam_prefs.h int UF_CAM_PREF_ask_integer_value(UF_CAM_PREF_t pref, int * value ) overview 概述 This function provides the …

如何看待程序员领域内的“内卷”现象?

要搞清楚这个问题,我首先就来阐释一下“内卷”的概念。 内卷本身是从一个学术名词演化为网络流行词的,本是指文化模式因达到某种最终形态,既无法保持稳定也不能转化为更高级的新形态,而只能在这种文化模式内部无限变得复杂的现象。…

TVS瞬态抑制二极管的工作原理和特点?|深圳比创达电子EMC

TVS二极管一般是用来防止端口瞬间的电压冲击造成后级电路的损坏。防止端口瞬间的电压冲击造成后级电路的损坏。有单向与双向之分,单向TVS一般应用于直流供电电路,双向TVS应用于交流供电电路。 TVS产品的额定瞬态功率应大于电路中可能出现的最大瞬态浪涌…

层层剥开Android14升级后异常弹框的神秘面纱

本篇文章将会通过研究源码的方式给您讲述Android系统升级到Android14后出现的两个异常弹框并给出消除它们的方案。闲话少叙,我们开始。 问题描述 在Android 14升级后,出现两个弹窗的异常情况。这里是异常的截图: 接下来,我们对这…

第一个Maven项目

(一)准备工作 1、从官网下载压缩包:apache-maven-3.5.4-bin,然后解压到D盘没有中文的目录。 2、配置环境变量: 在左下角win打开“设置”,搜索“高级系统设置”,点击“高级”,点击“环境变量”&…