【JaveEE】网络编程之TCP套接字、UDP套接字

news2024/11/18 8:19:53

目录

1.网络编程的基本概念

1.1为什么需要网络编程 

1.2服务端与用户端

1.3网络编程五元组 

1.4套接字的概念

2.UDP套接字编程

2.1UDP套接字的特点

 2.2UDP套接字API

2.2.1DatagramSocket类

2.2.2DatagramPacket类 

2.2.3基于UDP的回显程序

2.2.4基于UDP的单词查询 

3.TCP套接字编程

3.1TCP套接字的特点

3.2TCP中的长短连接

3.3TCP套接字的API

3.3.2Socket类

3.3.3基于TCP的回显程序

3.3.4对TCP回显程序的优化


1.网络编程的基本概念

网络编程,指网络上的主机,通过不同的进程,以编程的方式实现网络通信(或称为网络数据传输)。对于我们程序员来说,我们比较关注应用层到传输层这一操作,我们代码的书写是发生在应用层的,然后通过传输层提供的API(UDP和TCP)进行包装,再由应用层发送给传输层。

1.1为什么需要网络编程 

 这个最为直接的说话莫过于人民需要他了,哪里有需求,哪里就提供响应嘛。

相比于本地的资源,网络上有这更为丰富的资源,而网络上的资源又需要通过网络编程来上传,因此就相互督促相互促进了对方的发展。

1.2服务端与用户端

服务端:在常见的网络数据传输场景下,把提供服务的一方进程,称为服务端,可以提供对外服务。
客户端:获取服务的一方进程,称为客户端。

简单的说,客户端会接收到客户的请求,再将客户的请求发送给服务端;服务端将请求按照业务逻辑完成响应,再将响应返回给客户端,客户端再将响应按照操作显示或者运作。

1.3网络编程五元组 

  1. 源IP:就是发送方IP.
  2. 源端口:发送方端口号, 服务器需要手动指定, 客户端让系统随机分配即可.
  3. 目的IP: 接收方IP, 包含在拿到的数据报中, 服务器响应时的目的IP就在客户端发来的数据报中, 客户端发送请求时的目的IP就是服务器的IP.
  4. 目的端口: 接收方端口号包含在数据报中, 服务器响应时的目的端口就在客户端发来的数据报中, 客户端发送请求时的目的端口就是服务器的端口号.
  5. 协议类型:如UDP/TCP.

1.4套接字的概念

Socket(套接字)可以看成是两个网络应用程序进行通信时,各自通信连接中的端点,这是一个逻辑上的概念。Socket是由IP地址和端口结合的,提供向应用层进程传送数据包的机制 

套接字的表示方法:Socket=Ip接口:端口号

2.UDP套接字编程

2.1UDP套接字的特点

特点如下:

  • 无连接:不关心和谁对话,也不会刻意留意对方。
  • 不可靠的:不关心他收没收到。
  • 面向数据报:以一个UDP数据报为单位。
  • 全双工通信:一条路径,但是路径两方都可以对话。(双向对话)

全双工

 2.2UDP套接字API

UDP套接字的API中主要包括两个类 :1.DatagramSocket 2.DatagramPacket。

下面就开始介绍这两个类

2.2.1DatagramSocket类

 DatagramSocket类就是实例一个UDP版本的套接字也是就数据包套接字。Socket对象对应到系统中的一个特殊文件(socket文件),socket文件不是数据存储区域的一部分,而是对应到网卡这个硬件设备,为什么对应到网卡呢?因为网卡是一个硬件,对于代码而已,不好直接操作,因此将它抽象成了一个文件进行间接操作。

DatagramSocket类构造方法:

方法签名方法说明
DatagramSocket()创建一个UDP数据报套接字的Socket,绑定到本机任意一个随机端口
(一般用于客户端)
DatagramSocket(int
port)
创建一个UDP数据报套接字的Socket,绑定到本机指定的端口(一般用
于服务端)

我们一般使用第二个方法,我们知道端口号是在一个计算机中寻找一个程序的“门牌号”。实际操作时,如果端口号是系统随机绑定的话,我们就不知道我们服务端服务于哪一个客户端了,就没有办法找到客户端的家了。

DatagramSocket类方法:

方法签名方法说明
void
receive(DatagramPacket p)
从此套接字接收数据报(如果没有接收到数据报,该方法会阻
塞等待)
void send(DatagramPacket
p)
从此套接字发送数据报包(不会阻塞等待,直接发送)
void close()关闭此数据报套接字

第一个receive方法它的参数需要准备一个空的DatagramPacket对象(对象需要给予存储空间),它把DatagramPacket实例对象再装入到准备好的空的DatagramPacket对象中去 ,为什么这样做呢?就像我们平常接收东西时,我们需要一个载体来承接这个物件,举个例子吧,当我们盛饭时,我们不能够直接用手去捧着饭,而是需要一个空饭盒去接打的饭。

第二个send方法他是DatagramPacket实例对象载入到接收缓冲区。

第三个close方法,因为DatagramSocket类属于文件资源,当我们不用的时候,我们需要将它给手动关闭了。

2.2.2DatagramPacket类 

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和端口号

这两个构造方法都会使用到,第一个构造方法:他就是我们上方说的空的DatagramPacket对象也就是我们举例说的“空饭盒”,第二个构造方法是在我们将接收到的请求进行封装时使用的,假设我们接收到的请求是字符串,我们就要将它转化成byte数组,再算出长度,并且需要指定它要发送到那里去也就是SockerAddress类的一个子类InetSocketAddress类它里面包含目的ip和目的端口号。

DatagramPacket类方法:

方法签名方法说明
InetAddress
getAddress()
从接收的数据报中,获取发送端主机IP地址;或从发送的数据报中,获取
接收端主机IP地址
int getPort()从接收的数据报中,获取发送端主机的端口号;或从发送的数据报中,获
取接收端主机端口号
byte[] getData()获取数据报中的数据

2.2.3基于UDP的回显程序

UDP服务端:

服务器设计逻辑: 

  1.  创建DatagramSocket对象,指定服务器端口号。
  2. 服务器启动了,我们需要一个DatagramPacket实例运来当作载体,当没有请求时,在这里就会发生阻塞,有请求时,就写入到DatagramPacket实例好的载体中。
  3. 接收到数据后,我们将数据拆分成我们需要的格式,因为我们是一个回显,故我们只需将它改成字符串就行了,再调用process方法,在这里完成业务需求,我们这里只需返回字符串就像了。
  4. 将处理好的请求,再封装一下,封装成DatagramPacket实例对象,将这个响应发生使用send方法发送给客户端即可。
package UdpNetWork;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

//服务器端
public class UdpEchoServer {

    private DatagramSocket socket=null;
    public UdpEchoServer(int port) throws SocketException {
        this.socket=new DatagramSocket(port);
    }
    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //requestPacket是一个载体,receive方法会将发送过来的数据放入到这个载体中
            DatagramPacket requestPacket=new DatagramPacket(new byte[4096],4096);
            socket.receive(requestPacket);
            //将发来的数据拆解
            String request=new String(requestPacket.getData(),0, requestPacket.getLength());
            //做出响应
            String response=process(request);
            //将做出的响应包装起来,发给客户端
            DatagramPacket responsePacket=new DatagramPacket(response.getBytes(),response.getBytes().length,
                    requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //打印日志
            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 udpEchoServer=new UdpEchoServer(9090);
        udpEchoServer.start();
    }
}

 UDP客户端:

 客户端设计逻辑:

  1.  客户端需要知道服务端的位置,因此我们需要服务端的ip地址和端口号,故成员变量包含Ipserver、serverPort以及一个DatagramSocket对象(可以理解为整合ip和端口号)。
  2. 开始运行客户端,通过Scaner接收客户的请求。
  3. 拿到请求后,我们需要将它封装成DatagramPacket对象,发送给服务端。
  4. 发送完就等待服务端返回响应。
  5. 等到拿到响应之后,我们就可以对响应做出操作了,因为我们这里是回显,我们只需将返回过来的字符串打印出来即可。
package UdpNetWork;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.Scanner;

//客户端
public class UdpEchoClient {
    private DatagramSocket socket=null;
    private int serverPort;
    private String IpServer;

    public UdpEchoClient(int port, String ipServer) throws SocketException {
        socket=new DatagramSocket();
        this.serverPort=port;
        this.IpServer=ipServer;
    }
    public void start() throws IOException {
        Scanner sc=new Scanner(System.in);
        while (true) {
            System.out.print("输入字符->");
            String request=sc.next();
            //将输入的指令打包
            DatagramPacket requestPacket=new DatagramPacket(request.getBytes(),request.getBytes().length,
                    InetAddress.getByName(IpServer),serverPort);
            //发送给服务器端
            socket.send(requestPacket);
            DatagramPacket responsePacket=new DatagramPacket(new byte[4096], 4096);
            //接收服务器端的响应结果
            socket.receive(responsePacket);
            //打印服务端的响应
            String response=new String(responsePacket.getData(),0,responsePacket.getLength());
            //打印日志
            System.out.printf("req:%s,resp:%s\n",request,response);
        }
    }

    public static void main(String[] args) throws IOException {
        UdpEchoClient udpEchoClient=new UdpEchoClient(9090,"127.0.0.1");
        udpEchoClient.start();
    }
}

2.2.4基于UDP的单词查询 

对于这个服务端,我们不需要再写一边start方法了,我们可以直接让它继承udpEchoServer类,并且,我们在上方服务端,我们将对请求处理的部分拿出来当作了一个单独的函数,我们在将上方的函数进行重写就行了,还有就是,我们需要一个存储单词,并且它还方便查询的东西,我们就想到一个数据结构就是Map,刚好可以适合这个系统。

package UdpNetWork;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;

public class UdpDictServer extends UdpEchoServer{
    //字典表
    private Map<String, String> dict = new HashMap<>();

    public UdpDictServer(int port) throws SocketException {
        super(port);

        dict.put("dog", "小狗");
        dict.put("cat", "小猫");
        dict.put("fuck", "卧槽");
        // ........... 可以无限的添加很多很多数据. 有道词典和咱们相比, 就是人家的这个表更大!!
    }

    @Override
    public String process(String request) {
        return dict.getOrDefault(request, "该单词没有查到!");
    }

    public static void main(String[] args) throws IOException {
        UdpDictServer udpDictServer = new UdpDictServer(9090);
        udpDictServer.start();
    }
}

3.TCP套接字编程

3.1TCP套接字的特点

特点如下:

  1. 有链接:双方通信,都需要可以留意对方信息。
  2. 可靠传输:尽可能的将数据传输给对方,但也不能保证100%。
  3. 面向字节流:以一个字节传输为基本单位。
  4. 全双工:双方都可以向对方发送信息。

3.2TCP中的长短连接

TCP发送数据时,需要先建立连接,什么时候关闭连接就决定是短连接还是长连接
短连接:每次接收到数据并返回响应后,都关闭连接,即是短连接。也就是说,短连接只能一次收发数据。
长连接:不关闭连接,一直保持连接状态,双方不停的收发数据,即是长连接。也就是说,长连接可以多次收发数据。

长连接与短链接的区别:

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

3.3TCP套接字的API

TCP套接字的API中主要包含两个类:1.ServerSocket 2.Socket

下面介绍这两个类

3.3.1ServerSocket类

这个类是在看名字就很好理解,它主要用于服务端,它的作用是创建一个服务端套接字。

 ServerSocket类构造方法:

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

在实例对象时,我们就将端口号传进来,完成实例。

 ServerSocket类方法:

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

 第一个accept方法它是接收客户端的信息,如果客户端没有请求,那它就会阻塞等待,如果有请求,就会建立连接,它的返回值是一个套接字。

3.3.2Socket类

 这个类就是创建一个套接字实例对象,他的成员变量有两个:IP与端口号。

Socket类构造方法:

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

Socket类方法:

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

 3.3.3基于TCP的回显程序

服务端 

 服务器设计逻辑:

  1. 创建一个ServerSocket类对象,指定服务器端口号。
  2. 开始运行服务端;通过第一步实例好的对象调用accept方法,如果有无请求,就阻塞,如果有请求,就发到下面进行处理。
  3. 进入处理请求方法,将请求通过读接收缓冲区写入,再将写入的请求发给处理程序进行处理。
  4. 处理完毕后,将响应发给客服端。
package TcpNetWork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer {
    private ServerSocket serverSocket=null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //接收到客服端请求
            Socket clientSocket=serverSocket.accept();
            //将请求发给解决请求的方法
            processConnection(clientSocket);
        }
    }

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线了\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        try (InputStream inputStream=clientSocket.getInputStream();
             OutputStream outputStream=clientSocket.getOutputStream()){
            // 没有这个 scanner 和 printWriter, 完全可以!! 但是代价就是得一个字节一个字节扣, 找到哪个是请求的结束标记 \n
            // 不是不能做, 而是代码比较麻烦.
            // 为了简单, 把字节流包装好了更方便的字符流~~
            Scanner sc=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);
            while (true) {
                //1.接到客服端请求
                if (!sc.hasNext()) {
                    System.out.printf("[%s:%d] 客户端下线了\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
                    break;
                }
                String request=sc.next();
                //2.对请求做出响应
                String response=process(request);
                //3.把响应返回给客户端
                printWriter.println(response);
                printWriter.flush();
                System.out.printf("[%s:%d] request:%s response:%s ",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            clientSocket.close();
        }
    }

    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer=new TcpEchoServer(9999);
        tcpEchoServer.start();
    }
}

客户端

客户端设计逻辑:

  1. 创建一个Socket实例,指定服务器的ip和端口号。
  2. 开启客户端,输入请求,并刷新接收缓存区。
  3. 等到服务端给出响应,接收响应,对响应做出动作。
package TcpNetWork;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
   private Socket socket=null;

    public TcpEchoClient(int port, String serverIp) throws IOException {
        socket=new Socket(serverIp,port);
    }

    public void start() {
        Scanner sc=new Scanner(System.in);
        try(InputStream inputStream=socket.getInputStream();
            OutputStream outputStream=socket.getOutputStream()) {
            Scanner scannerFromSocket=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);
            while (true) {
                //1.从键盘上读取请求
                System.out.print("输入指令->");
                String request=sc.next();
                //2.将请求发送给服务器端,并刷新接收缓存区
                printWriter.println(request);
                printWriter.flush();
                //3.接收服务器端的信息
                String response=scannerFromSocket.next();
                //4.把信息打印到控制台
                System.out.printf("request:%s response:%s\n",request,response);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient=new TcpEchoClient(9999,"127.0.0.1");
        tcpEchoClient.start();
    }
}

3.3.4对TCP回显程序的优化

在上方的程序中,我们只能对一个客户端进行提供服务,这是因为我们在接收的部分给写成了死循环,如果出现第二个客户端时,第二个客户端只能进行等待。我们如何修改这个程序呢?这是我们就不得不提到多线程了,如果写成多线程的话,就可以处理多个程序了。

程序代码如下(服务端): 

package TcpNetWork;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoServer {
    private ServerSocket serverSocket=null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket=new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动");
        while (true) {
            //接收到客服端请求
            Socket clientSocket=serverSocket.accept();
            //将请求发给解决请求的方法
            Thread t=new Thread(()->{
                try {
                    processConnection(clientSocket);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d] 客户端上线了\n",clientSocket.getInetAddress().toString(),clientSocket.getPort());
        try (InputStream inputStream=clientSocket.getInputStream();
             OutputStream outputStream=clientSocket.getOutputStream()){
            // 没有这个 scanner 和 printWriter, 完全可以!! 但是代价就是得一个字节一个字节扣, 找到哪个是请求的结束标记 \n
            // 不是不能做, 而是代码比较麻烦.
            // 为了简单, 把字节流包装好了更方便的字符流~~
            Scanner sc=new Scanner(inputStream);
            PrintWriter printWriter=new PrintWriter(outputStream);
            while (true) {
                //1.接到客服端请求
                if (!sc.hasNext()) {
                    System.out.printf("[%s:%d] 客户端下线了\n", clientSocket.getInetAddress().toString(), clientSocket.getPort());
                    break;
                }
                String request=sc.next();
                //2.对请求做出响应
                String response=process(request);
                //3.把响应返回给客户端
                printWriter.println(response);
                printWriter.flush();
                System.out.printf("[%s:%d] request:%s response:%s ",clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
                System.out.println();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            clientSocket.close();
        }
    }

    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer tcpEchoServer=new TcpEchoServer(9999);
        tcpEchoServer.start();
    }
}

如果我们想要去验证这个程序是否可以对多个客户端提供服务,我们还需要对其修改一点配置,不然我们不能将同一个类运行两次。

 1.右键鼠标,选择修改运行配置 

 2.点开之后,点击修改选项 

 3.将允许多个实例打勾,这一我们就可以同时运行多个实例了。


写在最后:

🐣🐣🐣以上就是本文全部内容,如果对你有所帮助,希望能留下你的点赞+关注,我会更加努力的更新内容!非常感谢🧡🧡🧡

若本篇文章有错误的地方,欢迎大佬们指正!

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

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

相关文章

免疫力低会怎么样 什么情况会导致免疫降低

都说免疫力是很重要的&#xff0c;它会我们健康的第一道防线&#xff0c;但是当免疫力降低的时候&#xff0c;会出现哪些情况&#xff1f;为什么免疫力会降低&#xff1f; 免疫力是人体的防御系统&#xff0c;就像是维持人体正常运转的军队。免疫力的高低&#xff0c;一定程度上…

再探pytorch的Dataset和DataLoader

本文参加新星计划人工智能(Pytorch)赛道&#xff1a;https://bbs.csdn.net/topics/613989052本文从分类、检测、分割三大任务的角度来剖析pytorch得dataset和dataloader源码&#xff0c;可以让初学者深刻理解每个参数的由来和使用&#xff0c;并轻松自定义dataset。思考&#x…

SQL LIMIT

SQL LIMIT SQL LIMIT子句简介 要检索查询返回的行的一部分&#xff0c;请使用LIMIT和OFFSET子句。 以下说明了这些子句的语法&#xff1a; SELECT column_list FROMtable1 ORDER BY column_list LIMIT row_count OFFSET offset;在这个语法中&#xff0c; row_count确定将返…

Html5版贪吃蛇游戏制作(经典玩法)

回味经典小游戏&#xff0c;用Html5做了个贪吃蛇的小游戏&#xff0c;完成了核心经典玩法的功能。 游戏可以通过电脑的键盘“方向键”控制&#xff0c;也可以点击屏幕中的按钮进行控制。&#xff08;支持移动端哈&#xff09; 点击这里试玩 蛇的移动是在18 x 18的格子中进行移…

sqoop数据导入

创建数据库 mysql全表数据导入hdfs mysql查询数据导入hdfs mysql指定列导入hdfs 使用查询条件关键字将mysql数据导入hdfs mysql数据导入hive 创建数据库 hive中创建user表 create table users( id bigint, name string ) row format delimited fields terminated by &…

数据结构 - 归并排序 | C

思路分析 什么是归并&#xff1f; 示例&#xff1a;&#xff08;归并后的结果copy到原数组&#xff09; 逻辑&#xff1a; if (a[begin1] < a[begin2]) {tmp[i] a[begin1];} else {tmp[i] a[begin2];} 归并排序 分解到“有序”再归并 递归 int middle (left righ…

哈希——unordered系列关联式容器

目录 unordered系列关联式容器 概念 unordered_map 无序去重 operator[] unordered_set 无序去重 OJ练习题 重复n次的元素 两个数组的交集 两个数的交集二 底层结构 概念 哈希冲突 闭散列 结点的定义 扩容 字符串取模 插入 查找 删除 闭散列完整代码 开…

安卓远程控制软件哪个好用

如果您曾希望将个人电脑放在口袋里&#xff0c;那么您可能只需要安卓远程访问软件。 没有远程访问应用程序&#xff1a;使用和控制计算机的唯一方法是坐在计算机前并手动输入命令。 使用远程访问应用程序&#xff1a;您可以在世界任何地方通过 Internet 连接从您的安卓平板电…

【30天python从零到一】---第七天:列表和元组

&#x1f34e; 博客主页&#xff1a;&#x1f319;披星戴月的贾维斯 &#x1f34e; 欢迎关注&#xff1a;&#x1f44d;点赞&#x1f343;收藏&#x1f525;留言 &#x1f347;系列专栏&#xff1a;&#x1f319; Python专栏 &#x1f319;请不要相信胜利就像山坡上的蒲公英一样…

计算机组成原理---第五章中央处理器

&#xff08;一&#xff09;CPU 的功能和组成 CPU 的功能 Ⅰ 概述&#xff1a;当程序指令装入内存储器后&#xff0c;CPU 用来自动完成取指令和执行指令的任务。 Ⅱ CPU 的功能&#xff1a;①指令控制 ②操作控制 ③时间控制 ④数据加工 2.CPU 的基本组成 CPU 的基本部分为运…

【论文阅读】[JBHI] VLTENet、[ISBI]

[JBHI] VLTENet 论文连接&#xff1a;VLTENet: A Deep-Learning-Based Vertebra Localization and Tilt Estimation Network for Automatic Cobb Angle Estimation | IEEE Journals & Magazine | IEEE Xplore Published in: IEEE Journal of Biomedical and Health Infor…

9.1 相关分析

学习目标&#xff1a; 如果我要学习相关分析&#xff0c;我可能会按照以下步骤进行&#xff1a; 确定学习相关分析的目的和应用场景&#xff0c;例如研究两个变量之间的相关性、了解变量之间的关系、预测未来趋势等。学习相关分析的基本概念和原理&#xff0c;包括相关系数、…

VS——Visual Studio 2022 社区版——快捷键

VS——Visual Studio 2022 社区版——快捷键官网简介PDF完整PDF编辑编辑&#xff1a;常用快捷方式菜单栏 会显示 快捷键功能搜索大纲 折叠 展开Ctrl M M 切换官网 https://learn.microsoft.com/zh-cn/visualstudio/ide/default-keyboard-shortcuts-in-visual-studio?viewvs-2…

数据结构 — 【排序算法】

目录 1.排序的概念及其运用 1.1排序的概念 1.2排序运用 1.3 常见的排序算法 2.常见排序算法的实现 2.1 插入排序 直接插入排序 希尔排序 2.2 选择排序 直接选择排序 堆排序 2.3 交换排序 冒泡排序 快速排序 2.4 归并排序 2.5 非比较排序 计数排序 基数排序 3.排序算法…

【Unity入门】12.MonoBehaviour事件函数

【Unity入门】MonoBehaviour事件函数 大家好&#xff0c;我是Lampard~~ 欢迎来到Unity入门系列博客&#xff0c;所学知识来自B站阿发老师~感谢 &#xff08;一&#xff09;常用的事件函数 &#xff08;1&#xff09;start和update方法 之前我们写的脚本&#xff0c;会默认帮助…

4.3 分部积分法

学习目标&#xff1a; 学习分部积分法&#xff0c;我可能会按照以下步骤进行&#xff1a; 理解分部积分法的基本思想。分部积分法是一种通过对积分式中的不同部分进行乘积分解&#xff0c;然后对乘积中的某一项进行积分&#xff0c;对另一项进行微分&#xff0c;从而将原积分式…

NumPy 秘籍中文第二版:五、音频和图像处理

原文&#xff1a;NumPy Cookbook - Second Edition 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 在本章中&#xff0c;我们将介绍 NumPy 和 SciPy 的基本图像和音频&#xff08;WAV 文件&#xff09;处理。 在以下秘籍中&#xff0c;我们将使用 NumPy 对声音和图像进…

叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践

导读&#xff1a; 随着叮咚买菜业务的发展&#xff0c;不同的业务场景对数据分析提出了不同的需求&#xff0c;他们希望引入一款实时 OLAP 数据库&#xff0c;构建一个灵活的多维实时查询和分析的平台&#xff0c;统一数据的接入和查询方案&#xff0c;解决各业务线对数据高效实…

一键构建分布式云原生平台

目录专栏导读一、分布式云原生平台1、应用无所不能2、运行无处不在3、服务千行白业二、分布式云原生平台关键要素1、统一应用管理2、统一流量自治3、统一数据管理4、统一运维三、多云多集群已经广泛应用四、分布式云的优势&#xff1a;1、避免厂商锁定2、满足合规化要求3、增强…

收藏!7个国内「小众」的程序员社区

技术社区是大量开发者的集聚地&#xff0c;在技术社区可以了解到行业的最新进展&#xff0c;学习最前沿的技术&#xff0c;认识有相同爱好的朋友&#xff0c;在一起学习和交流。 国内知名的技术社区有CSDN、博客园、开源中国、51CTO&#xff0c;还有近两年火热的掘金&#xff…