网络编程+文件上传操作的理解

news2024/9/22 23:28:40

前言:

        概述:在网络通信协议下,不同计算机上运行的程序,进行数据传输
            比如:通信,视频通话,网游,邮件等
            只要是计算机之间通过网络进行数据传输,就有网络编程的存在

(下面单纯是在Java基础中了解了一下网络编程,感觉理解比较浅显,深入的知识可能得学Netty)


软件结构:

C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、红蜘蛛、飞秋等软件。

 B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有IE、谷歌、火狐等。

简单了解一下即可,知道在Java开发中大多情况都是B/S结构

通信三要素

第一个要素:[IP地址]:计算机的唯一标识,用于两台计算机之间的连接

互联网协议地址(Internet Protocol Address),俗称IP
            计算机的唯一标识

这个ip地址其实是会动态变化得,当你在一个局域网中连上网得时候,自动会被分配一个ip地址

 特殊的网址:代表的是本机地址,到了哪里都不会变,代表自己

        127.0.0.1 -> 固定不变
        localhost

注意这两个ip地址都是指向自己的主机的,不过这两个还是不同的原,如果处理不好可能也会发送跨域问题。

第二个要素:[协议]

TCP:面向连接协议
         需要先确认连接,才能进行数据交互
         三次握手:
            - 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
            - 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
            - 第三次握手,客户端再次向服务器端发送确认信息,确认连接。
            
         好处:数据安全,能给数据的传输提供一个安全的传输环境
         坏处:效率低
     
     UDP:面向无连接协议
         好处:效率高
         坏处:传输的数据不安全,容易丢失数据包

第三个要素: [端口号]

每一个应用程序的唯一标识

举个例子来理解这句话,比如我们电脑开了两个应用程序,qq,微信,

这两个应用程序会各自占用一个端口号,别的主机也开了这两个程序,别的主机想和我们发消息的话,微信发的信息,就会通过我们电脑微信占用的端口号传给上层应用



  用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

TCP协议中的三次握手和四次挥手:

三次握手:


- 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
- 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手,客户端再次向服务器端发送确认信息,确认连接。

经过三次握手,客户端就可以和服务端建立连接

为什么要三次握手?不是两次?

防止已失效的连接请求导致资源浪费和网络拥堵 GPT是这么说的,感觉讲的不是很明白

我来举一个例子

假设现在只有两次握手

客户端发送了一个连接请求给服务端,这个请求报文并没有丢失,只是因为网络延迟在某个网络结点滞留了很久,导致过了连接释放以后的时间,然后这个时候服务端才收到请求,服务端以为这是一个新的请求,就开始等待客户端的数据并且给客户端发送了一个确认报文,可是在客户端这边连接释放的时间已经过了,自然不会理会服务端发生的确认报文,这个时候,服务端就会等待,导致浪费资源。

采用“三次握手”的办法可以防止上述现象发生。例如刚才那种情况,client不会向server的确认发出确认。server由于收不到确认,就知道client并没有要求建立连接。"

这就很明白了,防止了服务器端的一直等待而浪费资源。

四次挥手:

- 第一次挥手:客户端向服务器端提出结束连接,让服务器做最后的准备工作。此时,客户端处于半关闭状态,即表示不再向服务器发送数据了,但是还可以接受数据。

- 第二次挥手:服务器接收到客户端释放连接的请求后,会将最后的数据发给客户端。并告知上层的应用进程不再接收数据。

- 第三次挥手:服务器发送完数据后,会给客户端发送一个释放连接的报文。那么客户端接收后就知道可以正式释放连接了。

- 第四次挥手:客户端接收到服务器最后的释放连接报文后,要回复一个彻底断开的报文。这样服务器收到后才会彻底释放连接。这里客户端,发送完最后的报文后,会等待2MSL,因为有可能服务器没有收到最后的报文,那么服务器迟迟没收到,就会再次给客户端发送释放连接的报文,此时客户端在等待时间范围内接收到,会重新发送最后的报文,并重新计时。如果等待2MSL后,没有收到,那么彻底断开。

TCP协议编程:

在了解TCP协议编程的之前,需要先了解两个对象:Socket和ServerSocket对象

秉承着在Java中万物皆是对象的理解方式:

  1. Socket:在TCP协议编程中,Socket类代表客户端的套接字。通过Socket对象,客户端可以与服务器建立连接,发送和接收数据。客户端通过Socket与服务器进行通信,发送请求并接收响应。Socket类提供了许多方法来管理连接、发送和接收数据等操作。

  2. ServerSocketServerSocket类代表服务器端的套接字。服务器端通过ServerSocket对象监听客户端的连接请求,一旦有客户端连接,ServerSocket会创建一个新的Socket对象来处理和该客户端的通信。通过ServerSocket,服务器端可以接受客户端的连接,并处理客户端发送的请求。

模拟客户端和服务端的交互:

编写客户端:

步骤:

1:创建Socket对象

2:调用Socket对象的getOutputStream想服务端发请求

3:调用socket中的getInputStream来读取服务端返回的数据

4:关流

public class Send {
    public static void main(String[] args) throws Exception {
        //1.创建Socket对象,指明服务端的ip以及端口号
        InetAddress ip = InetAddress.getByName("127.0.0.1");
        int port = 6666;
        Socket socket = new Socket(ip,port);
        //2.调用socket中的getOutputStream,往服务端发送请求
        byte[] bytes = "我需要资源".getBytes();
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write(bytes);
        //3.调用socket中的getInputStream,读取服务端响应回来的数据
        InputStream inputStream = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int len = inputStream.read(bytes1);
        System.out.println(new String(bytes1,0,len));
        //4.关流
        socket.close();
        outputStream.close();
        inputStream.close();
    }
}
编写服务端:

步骤:

1:创建ServerSocket对象,设置端口号

2:调用ServerSocket中的accept方法创建Socket对象,用于接收客户端发送的数据

3:调用Socket对象的getOutputStream想服务端发请求

4:调用socket中的getInputStream来读取服务端返回的数据

5:关流

public class Server {
    public static void main(String[] args) throws Exception{
        //1:创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(6666);
        //2:等待客户端的连接
        Socket socket = serverSocket.accept();
        //3: 获取客户端发过来的图片
        InputStream inputStream = socket.getInputStream();
        //4: UUID
        String s = UUID.randomUUID().toString();
        //5:将客户端发过来的图片读到磁盘中
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\java基础\\imgResult\\"+s+".jpg");
        //6:边读边写
        int len;
        byte[] bytes = new byte[1024];
        while((len = inputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);
        }
        System.out.println("======以下代码是给客户端的响应结果======");
        //7:接收客户端的响应结果
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("上传成功".getBytes());
        //8:关流
        serverSocket.close();
        socket.close();
        inputStream.close();
        fileOutputStream.close();
        outputStream.close();
    }
}

 


文件上传操作:

这一个部分主要有两块内容

第一个主要通过模拟客户端发送文件给服务端,服务端接收文件写入磁盘加深对TCP协议编程的理解

第二个理解阿里云文件上传中upload方法

第一个部分:

首先要完成上面那个功能,也是需要去写客户端和服务端的代码的。

客户端代码:

步骤:

  1. 创建Socket对象
  2. 创建文件对象,读取文件
  3. 调用Socket对象的getOutputStream想服务端发请求
  4. 边读文件边写文件
  5. 调用socket中的getInputStream来读取服务端返回的数据
  6. 关流
public class Client {
    public static void main(String[] args) throws Exception{
        //1:创建Socket对象,指明服务端的ip以及端口号
        InetAddress ip = InetAddress.getByName("127.0.0.1");
        int port = 6666;
        Socket socket = new Socket(ip,port);
        //2:从磁盘文件中读取图片资源
        FileInputStream file = new FileInputStream("E:\\java基础\\img\\1.jpg");
        //3: 调用socket中的getOutputStream,往服务端发送请求
        OutputStream outputStream = socket.getOutputStream();
        //4: 边读边写
        int len;
        byte[] bytes = new byte[1024];
        while((len = file.read(bytes))!=-1){
            outputStream.write(bytes,0,len);
        }
        socket.shutdownOutput();
        System.out.println("======以下代码是读取响应的结果======");
        //5:调用socket中的getInputStream,读取服务端响应回来的数据
        InputStream inputStream = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int len1 = inputStream.read(bytes1);
        System.out.println(new String(bytes1,0,len1));
        //6:关流
        socket.close();
        outputStream.close();
        inputStream.close();
        file.close();
    }
}

这里可以稍微说一下:socket.shutdownOutput();

用于关闭客户端并释放资源,如果你不主动关闭的话,服务端不知道你的文件已经传输完了,会一直等待。

服务端代码:

步骤:

  1. 创建ServerSocket对象,设置端口号
  2. 调用ServerSocket中的accept方法创建Socket对象,用于接收客户端发送的数据
  3. UUID
  4. 创建文件对象,将图片读到磁盘里
  5. 调用Socket对象的getOutputStream想服务端发请求
  6. 调用socket中的getInputStream来读取服务端返回的数据
  7. 关流
public class Server {
    public static void main(String[] args) throws Exception{
        //1:创建ServerSocket对象
        ServerSocket serverSocket = new ServerSocket(6666);
        //2:等待客户端的连接
        Socket socket = serverSocket.accept();
        //3: 获取客户端发过来的图片
        InputStream inputStream = socket.getInputStream();
        //4: UUID
        String s = UUID.randomUUID().toString();
        //5:将客户端发过来的图片读到磁盘中
        FileOutputStream fileOutputStream = new FileOutputStream("E:\\java基础\\imgResult\\"+s+".jpg");
        //6:边读边写
        int len;
        byte[] bytes = new byte[1024];
        while((len = inputStream.read(bytes))!=-1){
            fileOutputStream.write(bytes,0,len);
        }
        System.out.println("======以下代码是给客户端的响应结果======");
        //7:接收客户端的响应结果
        OutputStream outputStream = socket.getOutputStream();
        outputStream.write("上传成功".getBytes());
        //8:关流
        serverSocket.close();
        socket.close();
        inputStream.close();
        fileOutputStream.close();
        outputStream.close();
    }
}

 第二个部分:

下面是阿里云OSS的客户端上传文件的代码(我第一次接触的时候看不懂,只会用)

@Component
public class AliOSSUtils {
    @Autowired
    private AliOSSproperties aliOSSproperties;

    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile file) throws IOException {
        String endpoint = aliOSSproperties.getEndpoint();
        String accessKeyId = aliOSSproperties.getAccessKeyId();
        String accessKeySecret = aliOSSproperties.getAccessKeySecret();
        String bucketName = aliOSSproperties.getBucketName();
        // 获取上传的文件的输入流
        InputStream inputStream = file.getInputStream();

        // 避免文件覆盖
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);

        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }

}

虽然这上面步骤和第一部分的客户端代码有点不同

不过本质差不多

第一步:也是获取OSS客户端对象(前面需要一点配置信息):
String endpoint = aliOSSproperties.getEndpoint();
String accessKeyId = aliOSSproperties.getAccessKeyId();
String accessKeySecret = aliOSSproperties.getAccessKeySecret();
String bucketName = aliOSSproperties.getBucketName();
OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
第二步:获取文件对象:
// 获取上传的文件的输入流
InputStream inputStream = file.getInputStream();
第三步:UUID防止文件被覆盖:
// 避免文件覆盖
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));

首先说一下,我刚刚也尝试在第一部分的客户端代码中进行UUID的处理,发现不行,仔细看了一下,阿里云的文件对象是MultipartFile

MultipartFile是Spring框架中的一个接口,主要用于接收上传的文件数据,并提供了一些方法用于操作上传的文件。

 这个文件提供了一些api,所以能在客户端就UUID

第四步:上传文件:
//上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);
第五步:关闭ossClient:
ossClient.shutdown();

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

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

相关文章

深度学习 | CNN 基本原理

目录 1 什么是 CNN2 输入层3 卷积层3.1 卷积操作3.2 Padding 零填充3.3 处理彩色图像 4 池化层4.1 池化操作4.2 池化的平移不变性 5 全连接层6 输出层 前言 这篇博客不够详细,因为没有介绍卷积操作的具体计算;但是它介绍了 CNN 各层次的功能…

08 模型演化根本 深度学习推荐算法的五大范式

易经》“九三:君于终日乾乾;夕惕若,厉无咎”。九三是指阳爻在卦中处于第三位,已经到达中位,惕龙指这个阶段逐渐理性,德才已经显现,会引人注目;但要反思自己的不足,努力不…

昇思25天学习打卡营|MQ(mindquantum)编程实践

学AI还能赢奖品?每天30分钟,25天打通AI任督二脉 (qq.com) 安装 Packages # 安装 mindquantum, networkx !pip install mindquantum -i https://pypi.mirrors.ustc.edu.cn/simple !pip install networkx -i https://pypi.mirrors.ustc.edu.cn/simple 安装…

脸书登录指南:如何在同一台设备登录多个Facebook账号?

海外社媒营销人员和跨境卖家现在越来越依赖社交媒体平台来拓展业务和接触潜在客户,尤其是Facebook。然而,在进行脸书登录时,你可能会问:如何在同一台设备上登录多个Facebook账号,而不违反Facebook的使用条款&#xff1…

指针与数组笔试题解析

文章目录 1.一维数组1.1 整型数组1.2 字符数组 2. 二维数组3.指针笔试题3.1 练习13.2 练习23.3 练习3 数组名的意义: 1.sizeof(数组名),这里的数组表示整个数组,计算的整个数组的大小 2.&数组名,这里的数组名表示整个数组的&a…

【Diffusion学习】【生成式AI】Stable Diffusion、DALL-E、Imagen 背後共同的套路

文章目录 图片生成Framework 需要3个组件:相关论文【Stable Diffusion,DALL-E,Imagen】 具体介绍三个组件1. Text encoder介绍【结论:文字的encoder重要,Diffusion的模型不是很重要!】评估指标:…

用go实现限流算法

文章目录 固定窗口优缺点:适用场景:总结: 滑动窗口优缺点:适用场景:总结: 漏桶限流器优缺点:适用场景:总结: 令牌桶优缺点:适用场景:总结&#xf…

定义损失函数并以此训练和评估模型

基础神经网络模型搭建 【Pytorch】数据集的加载和处理(一) 【Pytorch】数据集的加载和处理(二) 损失函数计算模型输出和目标之间的距离。通过torch.nn 包可以定义一个负对数似然损失函数,负对数似然损失对于训练具有多…

炎炎夏日,这份锂电AGV叉车保养指南赶紧收藏!

AGV 随着工厂自动化、计算机集成制造系统技术的逐步发展以及柔性制造系统、自动化立体仓库的广泛应用,AGV(Automatic GuidedVehicle)即自动导引车作为联系和调节离散型物流系统以使其作业连续化的必要的自动化搬运装卸手段,其应用范围和技术水平得到了迅…

云服务器实际内存与购买不足量问题

君衍 一、本篇缘由二、问题研究1、dmidecode2、dmesg | grep -i memory 三、kdump四、解决方案1、卸载kdump-tools2、清理依赖包3、修改配置文件4、重新生成配置文件5、重启服务器6、再次查看 一、本篇缘由 本篇由于最近买了云服务器,之前基本在本地使用VMware进行虚…

初识单片机之点亮LED灯

1、前言 如果说编程的开始是Hello world,那么单片机的开始就是点亮LED灯,这个操作最直接的展示了单片机强大的控制功能,这里我就以直接点亮指定位置的LED灯的形式演示这个功能。 2、原理介绍 我的单片机的LED灯都是接在单片机的P1口,从P10~P…

【数据结构(邓俊辉)学习笔记】高级搜索树02——B树

文章目录 1. 大数据1.1 640 KB1.2 越来越大的数据1.3 越来越小的内存1.4 一秒与一天1.5 分级I/O1.6 1B 1KB 2. 结构2.1 观察体验2.2 多路平衡2.3 还是I/O2.4 深度统一2.5 阶次含义2.6 紧凑表示2.7 BTNode2.8 BTree 3. 查找3.1 算法过程3.2 操作实例3.3 算法实现3.4 主次成本3.…

YOLOv8白皮书-第Y8周:yolov8.yaml文件解读

本文为365天深度学习训练营中的学习记录博客 原作者:K同学啊|接辅导、项目定制 请根据YOLOv8n、YOLOv8s模型的结构输出,手写出YOLOv8l的模型输出 文件位置:./ultralytics/cfg/models/v8/yolov8.yaml 一、参数配置 # Parameters nc: 80 # n…

Bug:时间字段显示有问题

Bug:时间字段显示有问题 文章目录 Bug:时间字段显示有问题1、问题2、解决方法一:添加注解3、解决方法二:消息转换器自定义对象映射器配置消息转换器 1、问题 ​ 在后端传输时间给前端的时候,发现前端的时间显示有问题…

设计模式总结(设计模式的原则及分类)

1.什么是设计模式? 设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结…

自动化任务调度,轻松管理海量数据采集项目

摘要: 本文深入探讨了在数据驱动时代,如何通过自动化任务调度轻松驾驭海量数据采集项目,提升工作效率,确保数据处理的准确性和及时性。我们分享了一系列实用策略与工具推荐,帮助企业和开发者优化数据采集流程&#xf…

SQL 中的 EXISTS 子句:探究其用途与应用

目录 EXISTS 子句简介语法 EXISTS 与 NOT EXISTSEXISTS 子句的工作原理实际应用场景场景一:筛选存在关联数据的记录场景二:优化查询性能 EXISTS 与其他 SQL 结构的比较EXISTS vs. JOINEXISTS vs. IN 多重 EXISTS 条件在 UPDATE 语句中使用 EXISTS常见问题…

基于 AntV F2 的雷达图组件开发

本文由ScriptEcho平台提供技术支持 项目地址:传送门 基于 AntV F2 的雷达图组件开发 应用场景介绍 雷达图是一种多变量统计图表,用于可视化展示多个维度的数据。它通常用于比较不同对象的多个属性或指标,直观地反映各维度之间的差异和整体…

LoRaWAN协议

目录 一、介绍 1、LPWA是什么? 2、LoRa是什么? 3、LoRaWAN是什么? 4、浅谈LoRa与LoRaWAN的区别 5、LoRaWAN开发背景 6、LoRaWAN与NB-IOT如何选择? 二、LoRaWAN网络结构 1、组网结构 2、星型拓扑结构 三、数据格式 1、…

golang AST语法树解析

1. 源码示例 package mainimport ("context" )// Foo 结构体 type Foo struct {i int }// Bar 接口 type Bar interface {Do(ctx context.Context) error }// main方法 func main() {a : 1 }2. Golang中的AST golang官方提供的几个包,可以帮助我们进行A…