网络编程_TCP通信综合练习:

1

image.png

//client::
public class Client {
    public static void main(String[] args) throws IOException {
        //多次发送数据

        //创建socket对象,填写服务器的ip以及端口
        Socket s=new Socket("127.0.0.1",10000);

        //获取输出流
        OutputStream op = s.getOutputStream();

        //因为要不断发送数据,所以可以使用Sacnner录入数据,结合循环将数据发出去
        Scanner sc=new Scanner(System.in);
        while (true) {
            //键盘录入
            System.out.println("请输入一个数据");
            String str = sc.next();
            //如果输入886就退出发送
            if ("886".equals(str)){
                break;
            }
            op.write(str.getBytes());
        }
        //关流
        s.close();
    }
}
//Server:
public class Server {
    public static void main(String[] args) throws IOException {
        //不断接收
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);

        //等待客户端来连接
        Socket socket = ss.accept();
        //创建一个输入流对象
        InputStream is = socket.getInputStream();
        //转换流:字节转字符
        InputStreamReader isr = new InputStreamReader(is);

        int b;
        while ((b = isr.read()) != -1) {
            System.out.print((char) b);
        }
        //关流
        socket.close();//关闭通道
        ss.close();//关闭服务器

    }
}


先启动服务器,再启动客户端
控制台:
image.pngimage.png

2

image.png

//client
public class Client {
    public static void main(String[] args) throws IOException {
        //客户端:发送一条数据,接收服务端反馈的消息并打印
        //服务器:接收数据并打印,再给客户端反馈消息



        //1.创建Socket对象并连接服务端
        Socket socket = new Socket("127.0.0.1",10000);


        //2.写出数据
        String str = "见到你很高兴!";
        OutputStream os = socket.getOutputStream();
        os.write(str.getBytes());

        //写出一个结束标记,(结束输出流)
        socket.shutdownOutput();


        //3.接收服务端回写的数据
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        int b;
        while ((b = isr.read()) != -1){
            System.out.print((char)b);
        }


        //释放资源
        socket.close();


    }
}

//Server
public class Server {
    public static void main(String[] args) throws IOException {
        //客户端:发送一条数据,接收服务端反馈的消息并打印
        //服务器:接收数据并打印,再给客户端反馈消息


        //1.创建对象并绑定10000端口
        ServerSocket ss = new ServerSocket(10000);

        //2.等待客户端连接
        Socket socket = ss.accept();

        //3.socket中获取输入流读取数据
        InputStream is = socket.getInputStream();
        InputStreamReader isr = new InputStreamReader(is);
        int b;
        //细节:
        //read方法会从连接通道中读取数据
        //但是,需要有一个结束标记,此处的循环才会停止
        //否则,程序就会一直停在read方法这里,等待读取下面的数据
        while ((b = isr.read()) != -1){
            System.out.println((char)b);
        }

        //4.回写数据
        String str = "到底有多开心?";
        OutputStream os = socket.getOutputStream();
        os.write(str.getBytes());

        //释放资源
        socket.close();
        ss.close();


    }
}

image.pngimage.png

3

image.png
下面的例子是传输图片,所以使用字节流

//Client
public class Client {
    public static void main(String[] args) throws IOException {

        //创建Socket对象连接服务器
        Socket s = new Socket("127.0.0.1", 10000);

        //读取图片文件:使用字节流
        //图片较大:使用缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("..\\netcode\\clientdir\\a.jpg"));

        //在通道中获取字节流,输入数据到服务端
        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
        //边读边写
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.flush();

        //结束标识
        s.shutdownOutput();

        //接受服务端回馈:字节流-->字符流---->缓冲流
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

        int b;
        while((b=br.read())!=-1){
            System.out.print((char) b);
        }
        //关流
        s.close();
    }
}

//server
public class Server {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);
        //等待客户端连接
        Socket socket = ss.accept();

        //获取通道中传来的数据
        //字节流读取字节
        //缓冲流提升效率
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        //输出到本地
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("..\\netcode\\serverdir\\a.jpg"));

        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.flush();

        //返回信息:字节流-->字符流---->缓冲流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        bw.write("上传成功");
        bw.newLine();
        bw.flush();

        //关流
        socket.close();
        ss.close();
    }

}

image.pngimage.png

4.

image.png

//client
public class Client {
    public static void main(String[] args) throws IOException {

        //创建Socket对象连接服务器
        Socket s = new Socket("127.0.0.1", 10000);

        //读取图片文件:使用字节流
        //图片较大:使用缓冲流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("..\\netcode\\clientdir\\a.jpg"));

        //在通道中获取字节流,输入数据到服务端
        BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());
        //边读边写
        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.flush();

        //结束标识
        s.shutdownOutput();

        //接受服务端回馈:字节流-->字符流---->缓冲流
        BufferedReader br=new BufferedReader(new InputStreamReader(s.getInputStream()));

        int b;
        while((b=br.read())!=-1){
            System.out.print((char) b);
        }
        //关流
        s.close();
    }
}

//Server
public class Server {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);
        //等待客户端连接
        Socket socket = ss.accept();

        //获取通道中传来的数据
        //字节流读取字节
        //缓冲流提升效率
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());

        //随机uuid、
        String str = UUID.randomUUID().toString().replace("-", "");
        //输出到本地
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("..\\netcode\\serverdir\\" + str + ".jpg"));

        byte[] bytes = new byte[1024];
        int len;
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bos.flush();

        //返回信息:字节流-->字符流---->缓冲流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        bw.write("上传成功");
        bw.newLine();
        bw.flush();

        //关流
        socket.close();
        ss.close();
    }

}

image.png

5.

image.png
服务端不停止,用户端一直传
思路:可以在服务端使用循环嵌套:
如下:

public class Server {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);



        while (true) {
            //等待客户端连接
            Socket socket = ss.accept();

            //获取通道中传来的数据
            //字节流读取字节
            //缓冲流提升效率
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());

            //随机uuid、
            String str = UUID.randomUUID().toString().replace("-", "");
            //输出到本地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("..\\netcode\\serverdir\\" + str + ".jpg"));

            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);//当第一个用户还在传输时,服务端代码还会在这不断循环
            }
            bos.flush();

            //返回信息:字节流-->字符流---->缓冲流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
            bw.write("上传成功");
            bw.newLine();
            bw.flush();
            //关流
            socket.close();//断开当前通道
            //ss.close();//关闭服务器    ----这里不可以让服务器关闭
        }



    }
}

但是循环有弊端,它是一种单线程,如果说此时要传输的文件很大,当第一个用户还在传输时,服务端代码还会停止在第25行,此时就无法和第二个用户产生连接(只有完成一次循环后,才能和下一个用户进行数据连接),所以我们可以用多线程来改进。使多个用户可以同时传输数据,服务端也可以同时读取多个用户的数据

//多线程
public class MyThread  extends Thread{

    Socket socket;
     public MyThread (Socket socket){
         this.socket=socket;
     }


    @Override
    public void run() {
        //获取通道中传来的数据
        //字节流读取字节
        //缓冲流提升效率
        try {
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            //随机uuid、
            String str = UUID.randomUUID().toString().replace("-", "");
            //输出到本地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("..\\netcode\\serverdir\\" + str + ".jpg"));

            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            bos.flush();

            //返回信息:字节流-->字符流---->缓冲流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

            bw.write("上传成功");
            bw.newLine();
            bw.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //5.释放资源
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

//Server
public class Server {
    public static void main(String[] args) throws IOException {
        //创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);

        while (true) {
            //等待客户端连接
            Socket socket = ss.accept();
            new MyThread(socket).start();
            //ss.close();
        }

    }
}

//client....

6.

image.png
使用自定义线程池

//Server
public class Server {
    public static void main(String[] args) throws IOException {


        //1创建线程池对象
        ThreadPoolExecutor pool = new ThreadPoolExecutor(
                3,//核心线程数量
                16,//线程池总大小
                60,//空闲时间
                TimeUnit.SECONDS,//单位
                new ArrayBlockingQueue<>(2),//队列
                Executors.defaultThreadFactory(),//线程工厂,让线程池如何创建线程对象
                new ThreadPoolExecutor.AbortPolicy()//拒绝策略
        );

        //2创建ServerSocket对象
        ServerSocket ss = new ServerSocket(10000);

        while (true) {
            //3等待客户端连接
            Socket socket = ss.accept();
            //开启一条线程
            //一个用户就对应服务端的一条线程

            //调用submit方法传入myRunnable对象
            pool.submit((new MyRunnable(socket)));
            //ss.close();
        }

    }
}
//MyRunnable
public class MyRunnable implements Runnable {

    Socket socket;
     public MyRunnable(Socket socket){
         this.socket=socket;
     }


    @Override
    public void run() {
        //获取通道中传来的数据
        //字节流读取字节
        //缓冲流提升效率
        try {
            BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
            //随机uuid、
            String str = UUID.randomUUID().toString().replace("-", "");
            //输出到本地
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("..\\netcode\\serverdir\\" + str + ".jpg"));

            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, len);
            }
            bos.flush();

            //返回信息:字节流-->字符流---->缓冲流
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

            bw.write("上传成功");
            bw.newLine();
            bw.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //5.释放资源
            if (socket!=null){
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
//client.....


7.

image.png

public class Server {
    public static void main(String[] args) throws IOException {
        //客户端:多次发送数据
        //服务器:接收多次接收数据,并打印

        //1.创建对象绑定10000端口
        ServerSocket ss = new ServerSocket(10000);

        //2.等待客户端来连接
        Socket socket = ss.accept();

        //3.读取数据
        InputStreamReader isr = new InputStreamReader(socket.getInputStream());
        int b;
        while ((b = isr.read()) != -1){
            System.out.print((char)b);
        }

        //4.释放资源
        socket.close();
        ss.close();

    }
}

首先启动服务端:
再在浏览器输入:
image.png
获得到数据:
image.png

8.

image.png
client

package A;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Client1 {
    public static void main(String[] args) throws IOException {
        /**
         * 每一个客户端都是一个线程
         */


        while (true) {
            //1.与服务端建立连接
            Socket socket = new Socket("127.0.0.1", 10000);
            System.out.println("服务器已连接");
            //2生成聊天界面
            System.out.println("==============欢迎来到黑马聊天室================");
            System.out.println("1登录");
            System.out.println("2注册");
            System.out.println("请输入您的选择:");
            //3键盘录入
            Scanner sc = new Scanner(System.in);
            String choose = sc.nextLine();
            //判断:
            switch (choose) {
                case "1":
                    //登录逻辑
                    login(socket);
                    break;
                case "2":
                    //注册逻辑

                    break;
                default:
                    System.out.println("没有该选项");

            }
        }
    }

    /**
     * //登录
     *
     * @param socket
     * @throws IOException
     */
    private static void login(Socket socket) throws IOException {
        //1输入账户和密码
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名");
        String username = sc.nextLine();
        System.out.println("请输入密码");
        String password = sc.nextLine();

        //***登录要求使用username=zhangsan&password=123这种格式发给服务端
        //2拼接
        StringBuilder sb = new StringBuilder();
        sb.append("username=").append(username).append("&password=").append(password);

        //3提交给服务器验证
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        //第一次是告诉服务器是此时登陆操作是什么
        bw.write("login");
        bw.newLine();//这两个要配套使用
        bw.flush();
        //第二次告诉服务器用户端输入的账号密码
        bw.write(sb.toString());
        bw.newLine();
        bw.flush();

        //接收服务端的回馈消息
        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String message = br.readLine();

        if ("1".equals(message)) {
            System.out.println("登陆成功,可以开始聊天");

            //开一条单独的线程,专门用来接收服务端转发过来的聊天记录
            new Thread(new ClientMyRunnable(socket)).start();


            //将要说的话传给服务器,交给服务器转发给其他客户端
            talk2All(bw);
        } else if ("2".equals(message)) {
            System.out.println("密码不正确");
        } else {
            System.out.println("用户名不存在,请先注册");
        }
    }

    private static void talk2All(BufferedWriter bw) throws IOException {
        Scanner sc = new Scanner(System.in);
        while (true) {
            System.out.println("请输入你要说的话");
            String message = sc.nextLine();
            bw.write(message);
            bw.newLine();
            bw.flush();
        }


    }
}

class ClientMyRunnable implements Runnable {
    Socket socket;

    //构造
    public ClientMyRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        //循环包裹,不断读取服务端发过来的信息(接受群发消息)
        while (true) {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                String message = br.readLine();
                System.out.println(message);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

    }
}


server

package A;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.Buffer;
import java.nio.file.attribute.UserPrincipal;
import java.util.ArrayList;
import java.util.Properties;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Server {
    //成员位置方便调用
  static  ArrayList<Socket>list=new ArrayList<>();

    public static void main(String[] args) throws IOException {
        //1创建ServerSocket对象,并连接10000端口
        ServerSocket ss = new ServerSocket(10000);

        //2把本地文件中的正确用户名和密码都获取到
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream("..\\Chat\\account.txt");
        prop.load(fis);
        fis.close();
        //只要来了一个客户端,就开一个条线程
        while (true) {
            //等待服务端连接
            Socket socket = ss.accept();
            System.out.println("有客户端来连接");
            //开始处理线程任务
            new Thread(new MyRunnable(socket, prop)).start();
        }
    }
}

//-----------------------------------------------------------------------
class MyRunnable implements Runnable {
    Socket socket;
    Properties prop;

    //构造
    public MyRunnable(Socket socket, Properties prop) {
        this.socket = socket;
        this.prop = prop;
    }

    @Override
    public void run() {
        /**
         * 每一个线程要做的事情
         */
        try {
            //1读取客户端传来的信息
            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            //第一次读取的是用户的操作
            String choose = br.readLine();
            while (true) {
                switch (choose) {
                    case "login" -> login(br);
                    case "register" -> register();
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 1.获取用户端输入的帐号、密码
     * 2.与正确的账号密码比较
     * 3.写出不同情况的返回信息
     */
    public void login(BufferedReader br) throws IOException {
        System.out.println("用户执行了登陆操作");
        //第二次读取的是用户端传递过来的拼接信息:username=zhangsan&password=123
        String userInfo = br.readLine();
        //获取真正的账号密码:切割
        String s1 = userInfo.split("&")[0];
        String s2 = userInfo.split("&")[1];
        String usernameInput = s1.split("=")[1];
        String passwordInput = s2.split("=")[1];
        System.out.println("账号是:" + usernameInput);
        System.out.println("密码是:" + passwordInput);

        //比较
        if (prop.containsKey(usernameInput)) {
            //用户名一致,就比较密码
            //先获取当前正确密码
            String rellyPassword = (String) prop.get(usernameInput);
            if (passwordInput.equals(rellyPassword)) {
                //登陆成功,给用户端返回信息
                messageToClient("1");//登陆成功,可以开始聊天
                //登陆成功后需要将当前socket对象存储起来
                Server.list.add(socket);
                //接收客户端发送的信息并打印在控制台
                talk2All(br,usernameInput);
            } else {
                //密码不正确,给用户端返回信息
                messageToClient("2");//密码不正确

            }
        } else {
            //用户名不存在,给用户端返回信息:
            messageToClient("3");//用户名不存在,请先注册

        }
    }

    private void talk2All(BufferedReader br, String usernameInput) throws IOException {
        //聊天死循环
        while(true){
            //接收客户端发送的信息
            String message = br.readLine();
            System.out.println(usernameInput+"发送过来了消息:"+message);

            //群发
            for (Socket s : Server.list) {
                //s以此表示每一个socket对象
                messageToClient(s,usernameInput+"发送过来了消息:"+message);
            }
        }
    }


    /**
     *因为三种情况:登陆成功、密码不正确、用户名不存在都要返回信息给客户端,所以干脆抽取成方法
     * @param message
     */
    public void messageToClient(String message) throws IOException {
        //获取输出流
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.newLine();
        bw.flush();
    }

    /**
     * 重载的messageToClient
     * @param socket
     * @param message
     */
    public void messageToClient(Socket socket,String message) throws IOException {
        //获取输出流,将数据写给当前的socket通道对象
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        bw.write(message);
        bw.newLine();
        bw.flush();
    }















    /**
     * 注册逻辑
     */
    private static void register() {
        System.out.println("用户执行了注册操作");
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用RK3588开发板使用 SFTP 互传-windows与开发板互传

MobaXterm 软件网盘下载路径&#xff1a;“iTOP-3588 开发板\02_【iTOP-RK3588 开发板】开发资料\04_iTOP-3588 开发板所需 PC 软件&#xff08;工具&#xff09;\02-MobaXterm”。 打开 MobaXterm 创建一个 SFTP 会话&#xff0c;如下图所示&#xff1a; 输入密码 topeet 进入…

【目标跟踪】提供一种简单跟踪测距方法(c++)

文章目录 一、前言二、c代码2.1、Tracking2.2、KalmanTracking2.3、Hungarian2.4、TrackingInfo 三、调用示例四、结果 一、前言 在许多目标检测应用场景中&#xff0c;完完全全依赖目标检测对下游是很难做出有效判断&#xff0c;如漏检。检测后都会加入跟踪进行一些判断或者说…

深入理解 Vue3 中的 setup 函数

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

文章复现 | 差异分析和PPI网络构建

原文链接&#xff1a;差异分析和PPI网路图绘制教程 写在前面 在原文中&#xff0c;作者获得285个DEG&#xff0c;在此推文中共获得601个DEG。小杜的猜想是标准化的水段不同的原因吧&#xff0c;或是其他的原因。此外&#xff0c;惊奇的发现发表医学类的文章在附件中都不提供相…

快速入门:简单几步教你如何打开 JSON 文件

在当今的开发环境中&#xff0c;无论是前端还是后端开发者&#xff0c;几乎都会碰到需要处理 JSON&#xff08;JavaScript Object Notation&#xff09;文件的情况。JSON 格式因其轻量级、易于人阅读的结构而成为数据交换的首选格式。 什么是 JSON&#xff1f; JSON&#xff…

【数据库】Mysql索引

1、什么是索引&#xff1f;为什么要用索引&#xff1f; 1.1、索引的含义 数据库索引&#xff0c;是数据库管理系统中一个排序的数据结构&#xff0c;以协助快速查询&#xff0c;更新数据库中表的数据。索引的实现通常使用B树和变种的B树&#xff08;MySQL常用的索引就是B树&am…

MyBatis基础学习

一、MyBatis简介 二、MyBatis-HelloWorld 三、MyBatis-全局配置文件 四、MyBatis-映射文件 五、MyBatis-动态SQL 六、MyBatis-缓存机制 七、MyBatis-Spring整合 八、MyBatis-逆向工程 九、MyBatis-工作原理 十、MyBatis-插件开发

prometheus基于consul的服务发现

文章目录 一、基础二、安装consul下载地址启动consul访问consul 三、编写服务发现文件nodes.json四、prometheus配置consul发现修改prometheus.yml重启Prometheus 参考 一、基础 二、安装consul 下载地址 https://developer.hashicorp.com/consul/install 启动consul mkdi…

【深度优先搜索】【树】【有向图】【推荐】685. 冗余连接 II

LeetCode685. 冗余连接 II 在本问题中&#xff0c;有根树指满足以下条件的 有向 图。该树只有一个根节点&#xff0c;所有其他节点都是该根节点的后继。该树除了根节点之外的每一个节点都有且只有一个父节点&#xff0c;而根节点没有父节点。 输入一个有向图&#xff0c;该图由…

C#上位机与三菱PLC的通信07--使用第3方通讯库读写数据

1、通讯库介绍 mcprotocol 是一个基于 Node.js 的三菱 PLC MC 协议通信库&#xff0c;具有以下特点&#xff1a; 支持多种三菱 PLC MC 协议的设备&#xff0c;如 FX3U、Q03UDECPU、QJ71E71 等。 支持多种功能码和数据类型&#xff0c;如读取线圈&#xff08;M&#xff09;、…

工具:clang-format使用

Visual Studio 在扩展-》管理扩展-》联机-》搜索Format on Save (for VS2022)插件&#xff0c;并安装 安装需要关闭VS&#xff0c;安装后重新打开vs。 这样每次保存源文件时就会自动调用vs默认的clang-format.exe对源码进行缩进&#xff0c;空格等进行格式化 如果想使用自定…

MT8781核心板_MTK8781安卓核心板规格参数

MT8781安卓核心板以其强大的性能和高效的能耐备受瞩目。其八核CPU架构包括(2x Cortex-A76 2.2GHz 6x Cortex-A55 2.0GHz)&#xff0c;以及高性能的Arm Mali G57级GPU。同时&#xff0c;配备高达2,133MHz的LPDDR4X内存和快速的UFS 2.2级存储&#xff0c;大大加速了数据访问速…

定制红酒:为客户创造与众不同的品鉴体验

品鉴红酒不仅仅是为了享受美酒&#xff0c;更是一种生活方式的体现。云仓酒庄洒派深知这一点&#xff0c;并致力于为客户创造与众不同的品鉴体验。 1. 专业品鉴指导 云仓酒庄洒派拥有一支专业的品鉴团队&#xff0c;为客户提供详细的品鉴指导。无论是对于红酒的基本知识、品鉴…

qlv转mp4怎么操作?打破格式限制,转换技巧大揭秘

在数字媒体的世界里&#xff0c;视频格式的转换已成为我们日常生活中的常见需求。其中&#xff0c;将腾 讯视频特有的qlv格式转换为更通用的mp4格式&#xff0c;是许多用户面临的挑战。如何快速、高效地完成qlv转mp4&#xff1f;本文将为你揭开转换技巧的神秘面纱&#xff0c;让…

PMP和软件高项哪个含金量高?

PMP认证和高项二者可以说有相似之处又有不同之处&#xff0c;在知识点的方面他们的接触面非常广泛&#xff0c;多至80%&#xff0c;而在作用和适用方向上二者就有比较大些的区别&#xff0c;至于考哪个不考哪个的问题我身为过来人还是不建议去多想的&#xff0c;两个都照杀&…

【Linux】进程间通信——共享内存

文章目录 共享内存的概要创建共享内存shmget()参数keyshmget()参数sizeshmget()参数shmflg 删除共享内存挂载共享内存去关联 共享内存的概要 共享内存允许两个不相关的进程访问同一个逻辑内存。共享内存是在两个正在运行的进程之间传递数据的一种非常有效的方式。不同进程之间…

多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测

多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测 目录 多维时序 | Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现基于VMD-DBO-LSTM、VMD-LSTM、LSTM的多变量时间…

Eclipse - Formatter

Eclipse - Formatter References Window -> Preferences -> C/C -> Code Style -> Formatter BSD/Allman [built-in] or K& R [built-in] References [1] Yongqiang Cheng, https://yongqiang.blog.csdn.net/

电脑卡住不动了怎么办?三招解救你的电脑!

电脑卡住不动是一种常见的故障&#xff0c;可能会给用户带来困扰。这种情况可能由于多种原因引起&#xff0c;包括软件问题、硬件故障或系统错误。那么&#xff0c;电脑卡住不动了怎么办呢&#xff1f;在本文中&#xff0c;我们将介绍电脑卡住不动的可能原因&#xff0c;并提供…

Itext生成pdf文件,html转pdf时中文一直显示不出来

之前使用freemark模板渲染ftl页面,转出的pdf中&#xff0c;css2的很多样式好像不支持 改造成使用html页面来转pdf&#xff0c;css2的样式可以生效,itext是不支持css3的弹性布局的ITextRenderer pdfRenderer new ITextRenderer();// 添加字体设置ITextFontResolver fontResolve…