【Java EE初阶十四】网络编程TCP/IP协议(一)

 1. 网络编程

        通过网络,让两个主机之间能够进行通信->就这样的通信来完成一定的功能,进行网络编程的时候,需要操作系统给咱们提供一组API,通过这些API来完成编程;API可以认为是应用层和传输层之间交互的路径,其中Socket Api(可以认为是插座)通过这个一套Socket Api可以完成不同主机之间,不同系统之间的网络通信;   

        传输层提供的网络协议主要有两个tcp、udp:这两个协议的特性(工作原理差异很大,就会导致使用这两种协议进行网络编程,也会存在一定的差异)

1.1 TCP和UDP的区别

        1、TCP是有连接的,UDP是无连接的;

        这里的连接是抽象的概念,计算机中,这种抽象的连接是很常见的,此处的连接本质上就是建立连接的双方,各自保存对方的信息,即两台计算机建立连接,就是双方彼此保存了对方的关键信息;

        TCP想要通信,就需要先建立连接(即计算机保存对方的信息),做完之后,才能后续通信(如果A和B想要建立连接,但是B拒绝了,通信就无法完成建立)

        UDP想要通信,就直接发送数据报即可,不需要征得对方的同意,UDP自身也不会保存对方的信息(虽然UDP不知道,但是写程序的人得知道,UDP自己不保存对方的信息,但是调用UDP的socket api的时候就要把对方的位置信息等都传输过去)

        2、TCP是可靠传输的,UDP是不可靠传输的;

        网络上进行的通信,A->B发送一个信息,首先送到B的信息不可能做到100%送达,

所谓的可靠传输,就是退而求其次,当A->B发送一个消息,但是消息是不是达到B这一方,A这边自己是能感知到的,所以A在消息发送失败的时候就可以采取一定的措施(尝试重传之类的措施)

        TCP就内置了可靠的传输机制,但是UDP就没有内置可靠传输;

        可靠传输的不足:1、可靠传输所使用的机制更加复杂;2、可靠传输会导致消息的传输效率更加低;

        综上所述:

        TCP协议:发送方知道传输的数据是否成功的传输给接收方

        UDP协议:消息发出去,就不管了,不再考虑消息是否成功发送给接收方;

        3、TCP是面向字节流的,UDP是面向数据报的

        TCP也是和文件操作一样,以字节为单位来进行传输;UDP则是按照数据报(UDP有着自己严格的数据报格式)为单位来进行传输的

        4、TCP和UDP都是全双工的;

        一个信道,允许双向通信,就是全双工;一个信道,只能单向通信,就是半双工;

代码中使用一个socket对象,就可以发送数据也可以接收数据;

2. 关于UDP

2.1 UDP的socket api

        Socket其实是操作系统中的一个概念,本质上是一种特殊的文件;Socket就属于是把“网卡”这个设备给抽象成了文件了,往Socket文件里面写数据,就相当于通过网卡发送数据,从Socket文件里面读数据,就相当于通过网卡接收数据,(如此把网络通信和文件操作给统一了)

        DatagramSocket :

       Java中,就是用DatagramSocket这个类,来表示系统内部的socket文件;

        DatagramPacket: 使用这个类,来表示一个UDP数据报;UDP是面向数据报的,每一次传输都是以UDP数据报为基本单位的;

 2.2 基于UDP实现通信

        写一个简单的UDP的客户端/服务器通信的程序

        要求我们写的程序没有具体的业务逻辑,只是调用单纯的socket api,让客户端给服务器发送一个请求,且该请求是一个从控制台输入的字符串,服务器收到字符串之后,就会把这个字符串原封不动的返回给客户端,客户端在显示出来(即该服务器是回显服务器echo server)

1、读取请求并解析

        服务器和客户端都需要创建socket对象,但是服务器的socket一般要显示的指定一个端口号,而客户端的socket一般不能显式指定(不显式指定,此时系统就会自动分配一个随机的端口),客户端的端口号是不需要确定的,交给系统进行随机分配即可,如果我们手动指定确定的端口,就可以和别人的程序的端口号冲突;

Q:服务器这边手动指定端口号,难道就不会出现端口号冲突吗?为啥客户端在意这个冲突,而服务器不在意这个冲突?

A:首先服务器是在程序员手里面的,一个服务器上有哪些程序,这些程序都使用哪些端口,程序员都是可控的,且程序员在写代码的时候,就可以指定一个空闲的端口,给当前的服务器使用即可;其次客户端的情况就不一样了,因为客户端是在用户的电脑上的,一方面,用户有成千上万,每一个用户电脑上所装的程序都不一样,占用的短端口也不一样,林外一方面,用户这边如果出现了端口号冲突,用户这方面自己本身不知道是什么原因

        所以,客户端的端口号还是交给系统来进行分配,因为系统能保证肯定分配一个空闲的端口号;

        服务器一旦启动,就会立即执行到这里的receive这里的方法,此时客户端的请求可能还没有过来,此时遇到这种情况,receive就会直接阻塞,一直阻塞到客户端把请求发送过来为止;

2、根据请求计算响应(一般的服务器都会经历的过程)

        这个步骤是一个服务器程序最核心的步骤,我们当先的echo server不涉及到这些流程,只要求当请求过来就把请求当作响应,因为UDP是无连接的,所以udp自身不会保存数据要发送的对象信息,就需要每一次发送的时候,重新指定数据要发送到哪儿去;

 

3、把响应显示到客户端

4、打印一个日志,将我们进行的数据交互都打印出来

Q:为啥上述所写的代码中,没有写close,因为socket也是文件,不关闭的话就会出现之前我们所讲的文件资源泄露问题嘛?

A:        首先socket是文件描述符表中的一个表项,每一次打开一个文件,就会占用一个位置;文件描述符是在pcb上的(跟随的是进程)

        其次这个socket在整个程序的运行中都是需要使用的(不能提前关闭),当socket不需要使用的时候,意味着程序就要结束了,进程结束,此时随之的文件描述符表就会销毁了(pcb也会销毁),被销毁后资源就会被系统进行自动回收;

        最后,所谓出现泄露,是指代码中频繁打开文件,但是不会关闭,在一个进程的运行过程中,不断的打开文件,并逐渐消耗掉文件描述符表里面的内容,最终该资源就会被消耗殆尽了;但是,如果进程的生命周期很短,打开一下没多久就关闭了,谈不上所谓的资源泄露;

       综上所述,文件资源泄露这样的问题,在服务器这边是比较严重的,在客户端这边其实影响不大;

2.3 代码实现

2.3.1 服务器代码

package network;import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;public class UdpEchoServer {// 创建一个 DatagramSocket 对象. 后续操作网卡的基础.private DatagramSocket socket = null;public UdpEchoServer(int port) throws SocketException {// 这么写就是手动指定端口socket = new DatagramSocket(port);// 这么写就是让系统自动分配端口// socket = new DatagramSocket();}public void start() throws IOException {// 通过这个方法来启动服务器.System.out.println("服务器启动!");// 一个服务器程序中, 经常能看到 while true 这样的代码.while (true) {// 1. 读取请求并解析.DatagramPacket requestPacket = new DatagramPacket(new byte[4096], 4096);socket.receive(requestPacket);// 当前完成 receive 之后, 数据是以 二进制 的形式存储到 DatagramPacket 中了.// 要想能够把这里的数据给显示出来, 还需要把这个二进制数据给转成字符串.String request = new String(requestPacket.getData(), 0, requestPacket.getLength());// 2. 根据请求计算响应(一般的服务器都会经历的过程)//    由于此处是回显服务器, 请求是啥样, 响应就是啥样.String response = process(request);// 3. 把响应写回到客户端.//    搞一个响应对象, DatagramPacket//    往 DatagramPacket 里构造刚才的数据, 再通过 send 返回.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 {UdpEchoServer server = new UdpEchoServer(9090);server.start();}
}

2.3.2 客户端代码

package network;import java.io.IOException;
import java.net.*;
import java.util.Scanner;public class UdpEchoClient {private DatagramSocket socket = null;private String serverIp = "";private int serverPort = 0;public UdpEchoClient(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.print("-> ");String request = scanner.next();// 2. 把请求内容构造成 DatagramPacket 对象, 发给服务器.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 {//UdpEchoClient client = new UdpEchoClient("127.0.0.1", 9090);UdpEchoClient client = new UdpEchoClient("42.192.83.143", 9090);client.start();}
}

2.3.3 客户端和服务器交互逻辑

         分析如下:

1、服务期先启动,启动之后就开始进行循环,执行到receive这里并阻塞(此时还没有客户端过来)

2、客户端开始启动,也会先进入while循环,执行scanner.next,并且在这里进行阻塞,当用户在控制台输入字符串后,next就会返回,并且构造请求数据病发出来

3、客户端发出数据之后:

        服务器:就会从rfeceive中返回,进一步的执行解析请求为字符串,执行process操作,执行send操作

        客户端:继续往下执行,执行到receive服务器的响应;

4、客户端收到从服务器返回的数据之后,就会从receive中返回,执行这里的打印操作,也就把响应给显示出来了;

5、服务器这边完成过一次循环之后,又执行到receive这里;客户端这边完成一次循环之后,又执行到scanner.next这里,双双进入阻塞;

ps:本篇内容主要讲解关于UDP时间简单通信的过程,如果大家感兴趣的话就请一键三连哦!!!

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

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

相关文章

考研证件照可以自己用手机拍吗?考研证件照p过可以通过审核吗?考研证件照有什么要求

一、考研证件照可以自己用手机拍吗 现在的智能手机相机技术先进,大多都配备了高像素摄像头,使得自拍照片的质量有了大幅提升。相较于传统的证件照拍摄,使用手机自拍考研证件照理论上是可行的。然而,考研证件照需要满足一定的规定…

如何根据需求理解CPU、SoC和MCU的区别

在当今数字化的世界中,我们经常听到关于CPU、SoC和MCU的名词,它们都是计算机科学和电子工程领域中的重要组成部分。然而,这三者之间存在着明显的区别。本文将深入探讨CPU(中央处理器)、SoC(系统芯片&#x…

阿里云服务器部署配置选择全攻略

阿里云服务器配置怎么选择?根据实际使用场景选择,个人搭建网站可选2核2G配置,访问量大的话可以选择2核4G配置,企业部署Java、Python等开发环境可以选择2核8G配置,企业数据库、Web应用或APP可以选择4核8G配置或4核16G配…

【正点原子STM32连载】 第五十一章 T9拼音输入法实验 摘自【正点原子】APM32E103最小系统板使用指南

1)实验平台:正点原子APM32E103最小系统板 2)平台购买地址:https://detail.tmall.com/item.htm?id609294757420 3)全套实验源码手册视频下载地址: http://www.openedv.com/docs/boards/xiaoxitongban 第五…

图像识别之ResNet(结构详解以及代码实现)

前言 在人工智能的浪潮中,深度学习已经成为了推动计算机视觉、自然语言处理等领域突破的关键技术。在这众多技术中,ResNet(残差网络)无疑是一个闪耀的名字。自从2015年Kaiming He等人提出ResNet架构以来,它不仅在图像…

安全防御-第五次

新建NAT策略 新建NAT策略 双机热备 FW1 FW3 新建带宽策略 办公区限流

百度百家号旋转验证码识别研究

最近研究了一下图像识别,一直找到很好的应用场景,今天我就发现可以用百度的旋转验证码来做一个实验。没想到效果还挺好,下面就是实际的识别效果。 1、效果演示 2、如何识别 2.1准备数据集 首先需要使用爬虫,对验证码图片进行采…

引入成熟的Pytest自动化测试框架

虽然我们能使用脚本编写自动化测试框架,但没有必要重复找车轮子,引入成熟的自动化测试框架即可, Pytest是目前最成熟、功能最全面的Python测试框架之一,简单灵活、易于上手,可完全兼容其他测试框架如unitest&#xff…

Unittest+Selenium模块驱动自动化测试实战

UnittestSelenium自动化测试框架使用模块驱动测试模型将冗余的代码封装成类,且基于PageObject的自动化设计模式,通过分层的方式将页面对象、操作、业务分开处理。 1、首先创建自动化测试框架的文件模块架构,创建common、base、testcase、rep…

The Captainz NFT 概览与数据分析

作者:stellafootprint.network 编译:cicifootprint.network 数据源:The Captainz NFT Collection Dashboard The Captainz 是 Memeland 的旗舰系列,由 9,999 个实用性极强的 PFP 组成。持有者在 Memeland 宇宙中展开了一场神…

SG-9101CB(可编程+105℃晶体振荡器)

SG-9101CB 系列是一款高精度可编程性的晶体振荡器,能够在0.67 MHz至170 MHz的频率范围内以1ppm的步长精确调整频率。这款振荡器支持宽范围的电源电压(1.62 V至3.63V),并提供使能(OE)或待机(ST&a…

App启动优化笔记 1

app大致的启动流程。有Launcher进程,system_server进程,zygote进程,APP进程。 Launcher进程:启动activity来启动应用 system_server进程:(ams是其中的一个binder):发送一个socket消息给Zygote。 zygote进程:收到消息后,fork新的进程,---》app进程启动 APP进程:…

【复现】Panalog大数据日志审计系统 RCE漏洞_51

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一: 四.修复建议: 五. 搜索语法: 六.免责声明 一.概述 Panalog大数据日志审计系统定位于将大数据产品应用于高校、 公安、 政企、 医疗、 金融、 能源等行业之中,针对网络流…

【AGI视频】Sora的奇幻之旅:未来影视创作的无限可能

在五年后的未来,科技的发展为影视创作带来了翻天覆地的变化。其中,Sora视频生成软件成为了行业的翘楚,引领着全新的创作潮流。Sora基于先进的Transformer架构,将AI与人类的创造力完美结合,为观众带来了前所未有的视听盛…

【ArcGIS微课1000例】0103:导出点、线、面要素的折点坐标值

点要素对应的是一个或者若干个坐标,线要素对应的是对个坐标值对应的点连起来,面要素是多个坐标值对应的点连起来构成的封闭多边形。本文讲述导出点的坐标值。 文章目录 一、点要素坐标导出1. 计算点坐标2. 导出点坐标二、线要素坐标导出1. 生成线要素折点2. 计算折点坐标3. 导…

海外媒体发稿:8个提升影响力的日韩地区媒体发稿推广策略-华媒舍

在今天的数字化时代,媒体发稿推广成为企业和个人增加影响力的重要方式。特别是在日韩地区,这个拥有庞大媒体市场和活跃社交媒体用户的地区,正确的推广策略将对影响力的提升起到关键作用。我们将介绍8个提升影响力的日韩地区媒体发稿推广策略。…

Python面向对象:什么是面向对象程序设计

编程范式 编程即写程序or代码,具体是指程序猿用特定的语法数据结构算法编写代码,目的是用来告诉计算机如何执行任务。 如果把编程的过程比喻为练习武功,那么编程范式指的就是武林中的各种流派,而在编程的世界里最常见的两大流派就…

微信小程序:实现微信小程序应用首页开发 (本地生活首页)

文章目录 小程序应用页面开发1、创建项目并配置项目目录结构配置导航栏效果三、配置 tabBar 效果四、轮播图实现4.1 创建轮播图数据容器4.2 定义一个请求轮播图数据的接口4.3 页面加载调用 数据请求接口 五、九宫格实现5.1 获取九宫格数据5.2 结构和样式的完善六、图片布局实现…

基于 Amazon EC2 和 Amazon Systems Manager Session Manager 的堡垒机的设计和自动化实现

1. 背景 在很多企业的技术实现中,由于数据安全和合规性要求,大部分的应用服务都部署在私有云环境或专用网络中。为了满足开发人员和运维团队从本地数据中心安全访问云上资源的需求,采用堡垒机作为一种有效的解决方案变得尤为重要。 堡垒机的…

【漏洞复现】H3C SecParh堡垒机任意用户登录漏洞

Nx01 产品简介 H3C SecParh堡垒机是一款专业用于安全管理的堡垒机产品,它通过强大的访问控制功能和安全审计功能,实现对网络服务器的远程安全管理和监控。 Nx02 漏洞描述 H3C SecParh堡垒机的get_detail_view.php中存在任意用户登录漏洞。攻击者可以构建…