当前位置: 首页 > news >正文

【JavaEE初阶 — 网络编程】TCP流套接字编程

      c96f743646e841f8bb30b2d242197f2f.gif

ddb5ae16fc92401ea95b48766cb03d96.jpeg692a78aa0ec843629a817408c97a8b84.gif


    TCP流套接字编程    


    1. TCP & UDP 的区别    


TCP 的核心特点是面向字节流,读写数据的基本单位是字节 byte 


    2 API介绍    


    2.1 ServerSocket    


     定义     


ServerSocket 是创建 TCP 服务端 Socket 的API。


     构造方法     


方法签名
 
方法说明
 
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

所以服务器启动,需要绑定端口号


     方法      


方法签名
 
方法说明
 
 Socket accept()
 
开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待
 
 void close() 
 
关闭此套接字


    2.2  Socket    


  • Socket 是客户端 Socket ,或服务端中接收到客户端建立连接(accept方法)的请求后,返回的服务端Socket。

  • 不管是客户端还是服务端Socket,都是双方建立连接以后,保存的对端信息,及用来与对方收发数据的。

     构造方法     


方法签名方法说明
Socket(String host, int port)
 
创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

这个方法的两个参数,都是服务器的IP & 端口,这个版本的构造方法,就是给客户端用的,服务器怎么通过这个类来构造对象呢?后续再来看;


     方法      


方法签名方法说明
InetAddress getlnetAddress()
 
返回套接字所连接的地址
 
InputStream getlnputStream()
 
返回此套接字的输入流
 
OutputStream getOutputStream()
 
返回此套接字的输出流

TCP没有 send(),receive() 这样的操作,但是 TCP 调用 getlnputStream() 会得到个 InputStream 对象;调用 getOutputStream(),得到一个 OutputStream 对象,这两个对象是字节流对象

虽然 Socket 自身没有读写操作,但是 Socket 可以拿到字节流对象,就可以通过字节流对象,来进行读写操作;


     3. 通过TCP实现回显服务器        


     TCP Echo Server    


    创建关联对象    


通过构造方法,绑定关联的端口号 (和 UDP类似,都是在构造对象的时候,绑定端口号)


    实现 start()    


    处理客户端发送的连接    


TCP 和 UDP 服务器 start() 的主循环的第一步有所区别:


  • UDP 进入主循环,就可以直接处理请求,根据请求计算响应,把响应返回客户端;
  • TCP服务器 ,进入主循环后,因为 TCP 是有连接的,所以第一步是先处理客户端发来的连接;
  • 这个连接就类似于打电话,在客户端打电话给服务器时,服务器要先接通电话,才可以进行后续的正常通信;

所以TCP服务器进入主循环的第一步,就是进行接通电话的操作,而拨号操作,是客户端来完成的;

调用 ServerSocket 对象底下的 accept() 方法,起到接听电话的作用;


还需要接收 accept() 方法的返回值:

  • 如果客户端和服务器确实已经建立连接了,那 accept() 是可以拿到这个请求连接的;
  • 如果客户端没有发起连接,那么 accept() 就会产生阻塞 ,和前面的 receive() 类似;

TCP 服务器后续通过对clientSocket 进行读写数据,来和客户端进行通信;


    进一步理解 ServerSocket 和 Socket 的职责划分    


    处理一个客户端的连接        

处理连接的过程比较复杂,因此我们把这个操作封装成一个方法;

可能会涉及到多个客户端的请求和响应,如果服务器接收到多个请求,就要返还给客户端多个响应;


    服务器与客户端成功连接,打印日志: 

这两个方法可以拿到对端(客户端)的 IP & 端口号;


    获取输入流对象&输出流对象     

打印出客户端的IP&端口号后,就需要进一步地处理客户端的请求和响应,需要借助 Socket 类内置的 InputStream & OutputStream 来处理这些请求和响应

这里获取到的是输入流对象,后续提供这个对象,来读取客户端的请求;


接下来获取输出流对象,并且处理异常:


拿到输入流对象&输出流对象后,后续读取请求,就使用输入流对象;返回响应,就把响应的内容写入输出流对象中; 


接下来,在 try 的代码块中,实现读取请求和返回响应的操作,这些操作分成三步

  1. 读取请求并解析 
  2. 根据请求计算响应
  3. 返回响应给客户端

因为在一次连接中,这三个操作可能会解析多次,所以我们提供 while 循环来处理


    读取请求    

下列操作,读取到的请求是一个字节数组,还需要手动把字节数组再转成字符串,才方便后续的处理和打印:


我们可以借助 Scanner 来进行更简单直接的读取操作,既可以读请求,读出来的请求又已经是一个字符串;

 

  • 把刚刚从 Socket 中拿到的 InputStream 填入 Scanner 中,后续通过 Scanner 直接读取请求中的内容;
  • 如果 Scanner 没有再读取到数据,说明连接断开,就可以结束循环了

所以读取请求,可以直接借助 read(),也可以借助 Scanner 来辅助完成

    补充     

  • Scanner 可以控制处理台输入,又可以控制处理文件的输入,还可以控制处理网络的输入;
  • Scanner 的构造方法:

  • Scanner 的构造方法,填入的是一个InputStream 对象

    根据请求计算响应    

  • 当前编写的是一个回显服务器代码,所以可以直接在计算响应的逻辑返回请求即可


     返回响应给客户端    

下列写法,会直接拿到 response 中的字节数组,然后通过 outputStream 提供的 write(),来写入输出流对象即可;

这种计算响应的方法,是提供字节的方式填充输出流对象;


除了上述写法,我们还可以利用字符流的方式:


这里的 writer 和 System.out 起到的的效果类似,所以 println,printf 等等都可以通过调用


    打印返回响应的日志和连接断开的日志    


    服务器一次连接可处理多个请求的原理   

服务器 start() 的代码块中, process() 方法处理请求返回响应的逻辑,相当于嵌套了两层 while 循环:

因此,可以在服务器与客户端的一次连接中,服务器处理多个请求;

如果在一次连接中,客户端发送多次请求,服务器就返还多个响应(打一次电话可以说一句话或者很多句话);


    补充     

  • 一个连接一个请求(短连接),一个连接多个请求(长连接);
  • 因为连接过程的开销非常大,所以在日常开发中,更主流的是长连接,一个连接处理多个请求;
  • 就好比锁消除,针对要加锁的多个逻辑,每个逻辑都进行加锁,开销非常大,所以更科学的做法是把这些逻辑合在一起,只进行一次加锁;(和领导汇报工作成果,应该在一次电话中一次性汇总完毕,而不是打多次电话。每次电话只汇报一个成果)

    TCP Echo Client    


     创建 Socket 对象    

Socket 在客户端和服务器都可以使用,服务器的 Socket 通过调用accept()拿到,但是客户端的 Socket 就需要通过实例来创建对象;

     实现客户端构造方法    

在客户端的构造方法中,传入服务器的IP和端口号;

传到构造方法中的字符串IP地址(类似127.0.0.1这样的字符串),不需要任何转换;


对比UDP 的客户端,TCP客户端在构造方法在实例Socket对象后,就会在底层和对端建立TCP连接,连接好后,服务器会记录对端的信息(实例化Socket对象时传入的IP和端口号);

因此,服务器的IP和端口号,在TCP客户端中就不需要再创建变量来保存了;


    从控制台中读取请求,发送给服务器    


    从控制台中读取用户输入信息作为请求    

为了实现客户端能够和服务器在一次连接的情况下,发送多次请求,我们设置一个循环:

这步操作可以读取刚刚输入控制台的一行信息,读取到的信息作为客户端的请求;


    拿到输入流&输出流    

之后就把这个请求写入 Socket 对象中,写的时候也需要拿到Socket对象的 InputStream 输入流& OutputStream 输出流;


为了使用方便,可以对拿到的输入流和输出流再套一层壳


    完善循环逻辑     

所以在主循环中,第一步操作是从控制台中读取用户输入,把读取到的输入设置为请求:


第二步就是把请求发送给服务器


第三步,就是读取服务器返回的响应,并且把读取到的响应打印到控制台


    客户端与服务器交互过程    


    区分客户端与服务器的 Socket 对象    

下列服务器和客户端的两个 socket 对象,分别在不同进程中,甚至在不同主机中,因此绝对不是同一个对象;

这两个对象存在密切的关联关系,可以把这两个 socket 对象理解为两部电话:

  • 接通这两部电话后,从A听筒说话,B可以听见;从B听筒说话,A可以听见(从一边对Socket对象写数据,另一边的 Socket 对象就可以读到);
  • 但是这两个对象绝对不是同一部电话;

    处理细节问题    

    问题一:冲刷缓冲区     

完善 main 方法


程序运行结果


关掉客户端:


再启动一次客户端,并且发送一个数据,并且一敲回车,发现没有反应:


为什么没有反应呢?因为其实刚刚客户端代码,并没有真的把请求发送出去:

这个操作只是把数据放到 “发送缓冲区” 中,还没有真正写入网卡里;


  •  发送缓冲区其实就是一块内存空间,对网络/硬盘写数据是一个非常低效的操作,如果频繁地调用这些比较低效的操作,程序运行是非常缓慢的;
  • 为了提高效率,就引入一个内存缓冲区,把要写入的数据都放入缓冲区中,再统一进行发送,这样可以减小写硬盘和写网络的次数;
  • 但是提高效率的同时,也会产生副作用,就是调用 writer.println 这样的操作,并没有真正地触发发送数据操作,而只是把数据写入缓冲区;
  • 当然,把数据写入缓冲区,而不是直接发送这样的行为,是 PrintWriter的行为,如果不套壳,是可以直接发送的;
  • 但是在实际开发中,广泛使用了缓冲区这样的概念,调用flush()来刷新缓冲区这个操作是非常关键的;

如何真正地把数据发送出去呢?我们要使用刷新操作(调用 flush() 方法来冲刷缓冲区),把缓冲区的数据强制写入 IO 设备中:


客户端服务器交互结果


    问题二:针对 hasNext 对一个完整请求/响应设置标识符    

 println 的操作,会自动加上一个 \n : 


但是如果在这个代码中不加这个 \n,直接使用 print行不行呢?


我们重新启动一下客户端,并且发送内容,发现客户端又没有反应了,并且服务器也没有读到信息:


造成上述原因,是因为 next() 的问题,修改成 print 后,客户端输入的数据也是发送到服务器上了,并且服务器也收到了,但是服务器并没有真正处理,因为服务器有一个hasNext()判断:


    补充    

  • hasNext() 的行为是,判断当前收到的数据是否包含“空白符”,什么是空白符呢?
  • 换行,回车,空格,制表符,翻页符......都是空白符;
  • 遇到空白符,hasNext()才会认为是一个完整的 next,否则在遇到空白符之前,hasNext() 都会阻塞。

所以刚刚在修改成 print 之后,发送的内容是不包含空白符的内容,hasNext() 就会阻塞而无法进入下面读取请求的逻辑;


    总结    


  • 使用 println,是在约定一个请求/响应,是在使用 \n 作为结束标记,对端在读取数据的时候,也会在读取到 \n 时,判断读取到一个完整的请求/响应;
  • 这是我们在使用TCP时,特别需要注意的事项,并且和UDP不一样;
  • UDP是以 DatagramPacket 作为单位的,但是TCP则是以字节为单位,但是实际上一个请求,往往是以多个字节构成的;
  • 到底多少个字节为一个完整的请求/响应,就需要程序员想办法标记出来,引入分割符是标记一次完整请求/响应的典型方式,不一定是换行,也可以是其他分割符; 

    问题三:根据不同Socket的生命周期判断是否需要手动关闭    

在TCP服务器刚刚编写的代码中,涉及两种Socket:

  • ServerSocket的生命周期,贯彻整个服务区进程,不需要手动关闭


  • clientSocket 的生命周期是一次连接,而不是整个服务器进程;

  • 所以每个客户端连接,都会创建一个新的 clientSocket,每个客户端断开,这个对象就应该 close() 了,但是当前代码并没有对 clientSocket 进行 close() 释放;
  • 没有在每次连接结束后,对 clientSocket 进行关闭,就会造成文件资源泄漏的问题(文件一直在打开,而不进行关闭,在打开到一定程度,会把文件描述表耗尽,就无法继续打开新文件)

  • 在 poccessConnection() 方法的逻辑执行完毕之后,我们就可以对 clientSocket 进行关闭

    总结    

  • 对于是否需要手动关闭 Socket ,需要我们分析请求它的生命周期是跟随整个进程,还是跟随某个环节;
  • 如果是跟随整个进程,那么可以不手动关闭 Socket;如果是每个请求都会创建应该 Socket,或者每一次连接都会创建一个 Socket,或者某一个环节的执行周期,会创建一个Socket,这样的情况,就需要我们手动关闭 Socket;
    问题四:服务器无法同时等待 accept() &等待已连接的客户端发送响应    

一个服务器能同时给多个客户端提供服务,那么刚刚编写的TCP服务器也可以处理多个请求吗?我们关掉客户端,再重新启动多个客户端:


    补充:修改同时启动多个客户端的IDEA设置    



IDEA 会默认只启动一个客户端,再启动别的客户端,会先关闭上一个启动的客户端;我们通过这里的设置,就可以让 IDEA 启动多个客户端;

设置好后,我们再来重新启动两个客户端, 并且先后发送请求:

结果在第二个客户端发送请求时,又卡住了,并且第一个创建的客户端多次发送请求的操作是没问题的,服务器都会有一个正常响应,但是第二个客户端无论怎么发送请求,都不会有响应:

并且我们通过服务器日志,可以发现,在第二个客户端上线时,并没有再次打印日志;

如果我们关掉第一个客户端,第二个客户端发送的请求,会马上被服务器接收,并且返回响应

所以当前代码,TCP服务器在同一时刻,只能处理一个客户端发送的请求;


针对上面出现的问题,我们对服务器的处理请求,返回响应这一块代码的关键逻辑进行分析:

如果同一时刻,有多个客户端对一个服务器进行连接,那么第一个和服务器连接的客户端1:

所以当前这个服务器代码,如果已经在处理一个客户端的请求,就没办法处理另一个客户端的请求,服务器代码会卡在循环中,无法重新调用 accept()连接新的服务器,直到连接的客户端退出,导致循环终止;


    总结    


  • 当前服务器代码,无法同时等待 accept 和 等待用户请求;在等待客户端发送请求的时候,没办法等待 accept() ,这个时候,如果有新的客户端连接,也无法接听电话(一个专业销售没办法在给先来的顾客讲解产品的时候,又去接待低级销售后面揽入店的顾客);
  • 因此,服务器的代码,导致服务器一次只能处理一个客户端发送的请求,这个代码是不合理的; 

    4. 服务器引入多线程    


如果只是单个线程,无法同时响应多个客户端;为了解决这个问题,此处给每个客户端都分配一个线程;


在服务器主线程中,就只是进行 accept(),每次有新的客户端 accept() 连接成功,就创建一个新的线程,又新线程负责完成,后续对客户端 Socket 对象的引用 clientSocket 的读写操作;

引入线程之后,重新启动服务器和两个客户端,可以发现服务器打印了两个带着不同端口号的日志;


因此,在引入线程之后,服务器可以一边等待请求,一边等待 accept() 连接新的客户端;



    5. 服务器引入线程池    


客户端连接,服务器就会创建新线程,客户端断开连接,客户端就会销毁线程,为了避免频繁创建销毁线程,也可以引入线程池;

线程池


对于在服务器引入线程池,一般不会使用 newFixedThreadPool,因为会创建一个固定线程数的线程池,意味着同时处理的客户端连接数目就固定了;

把任务都交到线程池中,线程池已经预先创建好了一些线程,提前创建好的线程就可以立刻投入工作,从而减少再去创建线程的开销;


线程不是越多越好,如果线程数量过多,CPU的利用率无法再被提高,还会导致系统调度速度下降;并且创建线程也是需要系统资源的,系统总体资源是有限的(一个主机差不多只能创建几千个线程);

无论是多线程,还是线程池,一个线程都对应一个客户端,并且一个主机创建的线程数目是有上限的,那如果有成千上万个客户端,同时访问一个服务器(一台主机),该怎么办呢?

IO多路复用/IO多路连接(这里不重点讲解,因为JVM中没有原生的 IO 多路复用 API,而是把API重新封装,已经不仅仅是多路复用了,后续会详细讲解针对 Java 的 IO多路复用所使用的 NIO,Netty 等知名网络框架,当前讲的IO是 BIO/Blocking IO);


    扩展    


基于BIO(同步阻塞IO)的长连接会一直占用系统资源。对于并发要求很高的服务端系统来说,这样的消耗是不能承受的。

  • 由于每个连接都需要不停的阻塞等待接收数据,所以每个连接都会在一个线程中运行。
  • 一次阻塞等待对应着一次请求、响应,不停处理也就是长连接的特性:一直不关闭连接,不停的处理请求。

实际应用时,服务端一般是基于NIO(即同步非阻塞IO)来实现长连接,性能可以极大的提升。 


    6. 长短连接    


TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接;


    长连接和短连接的概念    


  • 短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
  • 长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

    长连接和短连接区别    


  • 建立连接、关闭连接的耗时:短连接每次请求、响应都需要建立连接,关闭连接;而长连接只需要第一次建立连接,之后的请求、响应都可以直接传输。相对来说建立连接,关闭连接也是要耗时的,长连接效率更高。
  • 主动发送请求不同:短连接一般是客户端主动向服务端发送请求;而长连接可以是客户端主动发送请求,也可以是服务端主动发。
  • 两者的使用场景有不同:短连接适用于客户端请求频率不高的场景,如浏览网页等。长连接适用于客户端与服务端通信频繁的场景,如聊天室,实时游戏等。

   

   c96f743646e841f8bb30b2d242197f2f.gif

692a78aa0ec843629a817408c97a8b84.gif

相关文章:

【JavaEE初阶 — 网络编程】TCP流套接字编程

TCP流套接字编程 1. TCP & UDP 的区别 TCP 的核心特点是面向字节流,读写数据的基本单位是字节 byte 2 API介绍 2.1 ServerSocket 定义 ServerSocket 是创建 TCP 服务端 Socket 的API。 构造方法 方法签名 方法说明 ServerS…...

《气候变化研究进展》

《气候变化研究进展》设有气候系统变化、气候变化影响、气候变化适应、温室气体排放、对策论坛、简讯等栏目,其内容包括:国内外气候变化研究的最新成果与进展,以及与气候变化有关的交叉学科,如地球科学、生态与环境科学、人文与社…...

D2545电动工具调速专用控制电路芯片介绍【青牛科技】

概述: D2545 是一块频率、占空比可调的脉冲控制电路。可通过调节外接的电阻和电容大小来控制输出频率和占空比,达到控制电机转速的作用。 主要特点: ● 电源电压范围宽 ● 占空比可调 ● 静态功耗小 ● 抗干扰能力强 应用: ● …...

Unity 2020、2021、2022、2023、6000下载安装

Unity 2020、2021、2022、2023、6000 下载安装 以Unity 6000.0.24fc1下载安装为例: 打开 https://unity.cn/ 优三缔 官方网站; 点击【产品列表】→点击【查看更多】→选择自己需要的版本→点【开始使用】 点击【从Unity Hub下载】 以Windows为例&am…...

33 基于单片机的智能窗帘控制系统

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,采用DHT11温湿度传感器检测温湿度,滑动变阻器连接ADC0832数模转换器转换模拟,光敏传感器,采用GP2D12红外传感器,通过LCD1602显示屏显示…...

【CSS in Depth 2 精译_063】10.2 深入理解 CSS 容器查询中的容器

当前内容所在位置(可进入专栏查看其他译好的章节内容) 【第十章 CSS 容器查询】 ✔️ 10.1 容器查询的一个简单示例 10.1.1 容器尺寸查询的用法 10.2 深入理解容器 ✔️ 10.2.1 容器的类型 ✔️10.2.2 容器的名称 ✔️10.2.3 容器与模块化 CSS ✔️ 10.3…...

记录一次 k8s 节点内存不足的排查过程

背景:前端服务一直报404,查看k8s日志,没发现报错,但是发现pods多次重启。 排查过程: 查看pods日志,发现日志进不去。 kubectrl logs -f -n weave pod-name --tail 100查看pod describe kubectl describ…...

探索天空中的“名字”——用Landsat影像记录你的名字形状!

大家好!今天我发现了一个特别有趣的工具——NASA官网上有一个功能,允许你输入自己的名字,然后它会根据Landsat卫星影像显示出与你名字形状相符的地形图。是不是很酷?🎉 🌍 Landsat影像的神奇之处Landsat是N…...

QT6学习第四天 感受QT的文件编译

QT6学习第四天 感受QT的文件编译 使用纯代码编写程序新建工程 使用其他编辑器纯代码编写程序并在命令行运行使用 .ui 表单文件生成界面使用自定义 C 窗口类使用现成的QT Designer界面类 使用纯代码编写程序 我们知道QT Creator中可以用拖拽的方式在 .ui 文件上布局&#xff0c…...

透视投影(Perspective projection)与等距圆柱投影(Equirectangular projection)

一、透视投影 1.方法概述 Perspective projection(透视投影)是一种模拟人眼观察三维空间物体时的视觉效果的投影方法。它通过模拟观察者从一个特定视点观察三维场景的方式来创建二维图像。在透视投影中,远处的物体看起来比近处的物体小&…...

5 Java字符串操作

字符串操作 1、String类1.1 声明字符串1.2 创建字符串 1.3 字符串连接 /连接字符串连接其他数据类型 1.4 提取字符串信息获取字符串长度length()获取指定位置的字符 charAt()获取子字符串索引位置 indexOf()判断字符串首尾内容 startsWith()/endsWith()获取字符数组 toCharArra…...

【C++习题】17.二分查找算法_二分查找

文章目录 二分查找算法简介题目链接:题目描述:解法C 算法代码:图解总结朴素二分模板 二分查找算法简介 特点: 二分查找算法,是最恶心,细节最多,最容易写出死循环的算法。(而且非常难…...

Spring Boot英语知识网站:架构与开发

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式,是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示: 图4-1系统工作原理…...

Unity ShaderLab 实现网格爆炸

实现思路: 沿着3D物体每个面的法线,将面偏移一定的位置。 Shader Graph实现如下: Shader Lab 实现如下: Shader "Unlit/MeshExplode" {Properties{_MainTex ("Texture", 2D) "white" {}_Distan…...

2024/11/28学习日志

为了更好地记录并反思自己的学习状况,将每日学习的内容、时长、心得等记录于此日志。 于9月3日开始记录,计划每日记录,希望至少能够坚持一个学期。 学习内容: 数据结构: 拓扑排序。关键路径。 马原: 马…...

在shardingsphere执行存储过程

环境&#xff1a; springboot&#xff1a;2.5.2 数据库&#xff1a;Kingbase金仓V8R6 依赖&#xff1a; <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>sharding-jdbc-spring-boot-starter</artifactId></depende…...

1.文件目录操作

目录 &#x1f34c; ls - 列出目录内容 &#x1f349;cp - 复制文件或目录 &#x1f347;mv - 移动或重命名文件 &#x1f353; cd - 切换目录 &#x1f348; pwd - 打印工作目录 &#x1f352;mkdir - 创建目录 &#x1f351; rmdir - 删除空目录 &#x1f96d; touc…...

Vue单页面应用和多页面应用

在 Vue.js 中&#xff0c;“单页面”&#xff08;SPA&#xff0c;Single Page Application&#xff09;和"多页面"&#xff08;MPA&#xff0c;Multi Page Application&#xff09;是两种不同的应用结构&#xff0c;它们的差异主要体现在页面的加载方式、路由的使用、…...

Lombok :简化 Java 编程的得力工具

在 Java 开发过程中&#xff0c;常常需要编写大量的样板代码&#xff0c;例如构造函数、Getter 和 Setter 方法、equals 和 hashCode 方法等。这些代码虽然逻辑相对固定&#xff0c;但编写起来却较为繁琐且容易出错&#xff0c;并且会使代码显得冗长。Lombok 应运而生&#xff…...

AIGC引领金融大模型革命:未来已来

文章目录 金融大模型的应用场景1. **金融风险管理**2. **量化交易**3. **个性化投资建议**4. **金融欺诈检测和预防**5. **智能客户服务** 金融大模型开发面临的挑战应对策略《金融大模型开发基础与实践》亮点内容简介作者简介获取方式 在AIGC&#xff08;Artificial Intellige…...

DBA面试题-1

面临失业&#xff0c;整理一下面试题&#xff0c;找下家继续搬砖 主要参考&#xff1a;https://www.csdn.net/?spm1001.2101.3001.4476 略有修改 一、mysql有哪些数据类型 1&#xff0c; 整形 tinyint,smallint,medumint,int,bigint&#xff1b;分别占用1字节、2字节、3字节…...

用go语言写一个小服务

文章目录 简介重新想到go 小服务main.go部署测试 结束语 简介 golang的优势 响应速度&#xff1a; Go > Java > Python 内存占用&#xff1a; Go < Java < Python 从java转go&#xff0c;然后go又转java&#xff0c;感觉就是go虽然在编译、内存占用都强于java&am…...

亚马逊开发视频人工智能模型,The Information 报道

根据《The Information》周三的报道&#xff0c;电子商务巨头亚马逊&#xff08;AMZN&#xff09;已开发出一种新的生成式人工智能&#xff08;AI&#xff09;&#xff0c;不仅能处理文本&#xff0c;还能处理图片和视频&#xff0c;从而减少对人工智能初创公司Anthropic的依赖…...

WordCloud参数的用法:

-------------词云图集合------------- 用WordcloudPyQt5写个词云图生成器1.0 WordCloud去掉停用词&#xff08;fit_wordsgenerate&#xff09;的2种用法 通过词频来绘制词云图&#xff08;jiebaWordCloud&#xff09; Python教程95&#xff1a;去掉停用词词频统计jieba.toke…...

qml调用c++类内函数的三种方法

一.方法一&#xff1a;使用 Q_INVOKABLE 宏声明成员函数 1.第一步&#xff1a;依然需要新建一个类NetworkHandler: #include <QObject> class NetworkHandler : public QObject { Q_OBJECT public: explicit NetworkHandler(QObject *parent nullptr); Q_INVOKAB…...

NLP任务四大范式的进阶历程:从传统TF-IDF到Prompt-Tuning(提示词微调)

引言&#xff1a;从TF-IDF到Prompt-Tuning&#xff08;提示词微调&#xff09;&#xff0c;NLP的四次变革 自然语言处理&#xff08;NLP&#xff09;技术从最早的手工特征设计到如今的Prompt-Tuning&#xff0c;经历了四个重要阶段。随着技术的不断发展&#xff0c;我们的目标…...

GAMES101:现代计算机图形学入门-笔记-09

久违的101图形学回归咯 今天的话题应该是比较轻松的&#xff1a;聊一聊在渲染中比较先进的topics Advanced Light Transport 首先是介绍一系列比较先进的光线传播方法&#xff0c;有无偏的如BDPT&#xff08;双向路径追踪&#xff09;&#xff0c;MLT&#xff08;梅特罗波利斯…...

【Db First】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列 &#x1f…...

MySQL聚合查询分组查询联合查询

#对应代码练习 -- 创建考试成绩表 DROP TABLE IF EXISTS exam; CREATE TABLE exam ( id bigint, name VARCHAR(20), chinese DECIMAL(3,1), math DECIMAL(3,1), english DECIMAL(3,1) ); -- 插入测试数据 INSERT INTO exam (id,name, chinese, math, engli…...

告别照相馆!使用AI证件照工具HivisionIDPhotos打造在线证件照制作软件

文章目录 前言1. 安装Docker2. 本地部署HivisionIDPhotos3. 简单使用介绍4. 公网远程访问制作照片4.1 内网穿透工具安装4.2 创建远程连接公网地址 5. 配置固定公网地址 前言 本文主要介绍如何在Linux系统使用Docker快速部署一个AI证件照工具HivisionIDPhotos&#xff0c;并结合…...

富阳网站/泉州百度seo

闭包的意义&#xff1a;返回的函数对象&#xff0c;不仅仅是一个函数对象&#xff0c;在该函数外还包裹了一层作用域&#xff0c;这使得&#xff0c;该函数无论在何处调用&#xff0c;优先使用自己外层包裹的作用域 说明&#xff1a; 关于闭包&#xff0c;即函数定义和函数表达…...

常宁seo外包/seo草根博客

知识点&#xff1a; &#xff08;1&#xff09;变量的地址就是变量的指针。 &#xff08;2&#xff09;变量的值和变量的地址是不同的概念&#xff0c;变量的值是该变量在内存单元中的数据。 &#xff08;3&#xff09;用来存放指针/地址的变量就称为“指针变量”。 &#xff0…...

扬中热线网站/在线推广企业网站的方法

需求: 1.直接执行前端传来的任何sql语句&#xff0c;parameterType"String"&#xff0c; 2.对于任何sql语句&#xff0c;其返回值类型无法用resultMap在xml文件里配置或者返回具体的bean类型&#xff0c;因此设置resultType"java.util.Map"&#xff0c;但…...

内蒙古网站建设流程/关键词有哪些关联词

Paul Jaquays是一个多面手 Paul Jaquays是一个多面手&#xff0c;他在id Software里为QuakeⅡ设计关卡&#xff0c;并为QuakeⅢ做游戏和关卡设计。现在&#xff0c;还有谁不愿用他的东西呢&#xff1f;当Jaquays了解到Saqes的秘决后&#xff0c;他想出版一个关卡设计规则方面的…...

大型电子商务网站建设成本/衡阳有实力seo优化

昨天晚上玩的很晚&#xff0c;到家已经是凌晨1点多了&#xff0c;刚躺下就接到公司,说数据库有问题&#xff0c;电话基本解决&#xff0c;可躺下就开始失眠&#xff0c;一直到早晨6点多才迷糊一会。最近一直就失眠啊&#xff01;&#xff01;&#xff01; 做事要选择时机&#…...

公司让做网站违法/十大技能培训机构排名

Apple在 WWDC 上宣布&#xff0c;将向iOS 14.6、iPadOS 14.6、macOS 11.4 和tvOS 14.6及以上的用户提供空间音频和无损音频。 Apple 表示&#xff0c;在发布时将会提供超过 2000 万首无损质量的歌曲&#xff0c;到 2021 年底&#xff0c;整个 Apple Music 目录中将会提供超过 …...