Java分别用BIO、NIO实现简单的客户端服务器通信

news2024/10/6 12:19:14

分别用BIO、NIO实现客户端服务器通信

    • BIO
    • NIO
      • NIO演示(无Selector)
      • NIO演示(Selector)

前言:
Java I/O模型发展以及Netty网络模型的设计思想

BIO

Java BIO是Java平台上的BIO(Blocking I/O)模型,是Java中用于实现同步阻塞网络编程的一种方式。 在Java中,使用BIO模型需要通过Socket和ServerSocket类来完成网络连接和数据传输,但是由于BIO是同步阻塞的,所以会导致线程阻塞和资源浪费的问题。
因此,在高并发的网络编程场景中,通常会选择使用NIO(Non-blocking I/O)模型或者Netty等框架来实现。

在这里插入图片描述
服务端类代码

package com.yu.io.bio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(8081);
        while (true) {
            System.out.println("wait connect...");
            Socket clientSocket = serverSocket.accept();
            System.out.println(clientSocket.getPort() + "connected");
            System.out.println("start read...");

            byte[] readArr = new byte[1024];
            int read = clientSocket.getInputStream().read(readArr);
            if (read != -1) {
                System.out.println("read info : " + new String(readArr,0,read));
            }
            System.out.println("end read...");
            byte[] resBytes = "server response".getBytes();
            clientSocket.getOutputStream().write(resBytes);
            System.out.println("response info : " + new String(readArr,0,read));
            clientSocket.getOutputStream().flush();
        }
    }
}

客户端类代码

package com.yu.io.bio;

import java.io.IOException;
import java.net.Socket;

public class BIOClient {
    public static void main(String[] args) throws IOException {
        Socket clientSocket = new Socket("127.0.0.1",8081);
        byte[] resBytes = "client response".getBytes();
        clientSocket.getOutputStream().write(resBytes);
        System.out.println("response info : " + new String(resBytes));
        clientSocket.getOutputStream().flush();
        byte[] readArr = new byte[1024];
        int read = clientSocket.getInputStream().read(readArr);
        if (read != -1) {
            System.out.println("read info : " + new String(readArr,0,read));
        }
    }
}

NIO

Java NIO 能够支持非阻塞网络编程,可以理解为new io 或者no blok io 我更喜欢称之为new io,因为他不仅仅实现了非阻塞的网络编程方式,同时也封装了常用的网络编程api,更重要的是引入了多路复用器Selector的概念

在这里插入图片描述

下面的代码只是展示NIO非阻塞的实现,并没有展示NIO的真正用法

NIO演示(无Selector)

服务端类代码

package com.yu.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

public class NIOServer {

    public static List<SocketChannel> socketChannelList = new ArrayList<>();
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8081));
        serverSocketChannel.configureBlocking(false);
        System.out.println("server start...");
        while (true) {
            SocketChannel socketChannel = serverSocketChannel.accept();
            if (socketChannel != null) {
                System.out.println(socketChannel.socket().getPort() + " connected");
                socketChannel.configureBlocking(false);
                socketChannelList.add(socketChannel);
            }
            List<SocketChannel> rmChannelList = new ArrayList<>();
            for (SocketChannel channel : socketChannelList) {
                try {
                    doChannel(rmChannelList, channel);
                } catch (IOException ioException) {
                    //有客户端断开连接
                    System.out.println(channel.socket().getPort() + " disconnected");
                    channel.close();
                    rmChannelList.add(channel);
                }
            }
            socketChannelList.removeAll(rmChannelList);
        }
    }

    private static void doChannel(List<SocketChannel> rmChannelList, SocketChannel channel) throws IOException {
        ByteBuffer readByteBuffer = ByteBuffer.allocate(2048);
        int read = channel.read(readByteBuffer);
        String readStr = new String(readByteBuffer.array());
        if (read > 0) {
            System.out.println(channel.socket().getPort() + " : " + readStr);
            if (readStr.contains("hello")) {
                ByteBuffer sendByteBuffer = ByteBuffer.wrap("hello! I am robot.".getBytes());
                channel.write(sendByteBuffer);
                System.out.println("me : " + new String(sendByteBuffer.array()));
            }
            if (readStr.contains("old")) {
                ByteBuffer sendByteBuffer = ByteBuffer.wrap("I am 1 years old.".getBytes());
                channel.write(sendByteBuffer);
                System.out.println("me : " + new String(sendByteBuffer.array()));
            }
            if (readStr.contains("bey")) {
                ByteBuffer sendByteBuffer = ByteBuffer.wrap("see you.".getBytes());
                channel.write(sendByteBuffer);
                System.out.println("me : " + new String(sendByteBuffer.array()));
            }
        }
        if (read == -1) {
            rmChannelList.add(channel);
        }
    }
}

客户端类代码

package com.yu.io.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NIOClient {
    public static void main(String[] args) throws IOException {
        SocketChannel clientSocketChannel = SocketChannel.open();
        clientSocketChannel.connect(new InetSocketAddress("127.0.0.1",8081));
        clientSocketChannel.configureBlocking(false);
        String sendStr = "hello! I am client " + clientSocketChannel.socket().getPort() + ".";
        ByteBuffer sendByteBuffer = ByteBuffer.wrap(sendStr.getBytes());
        clientSocketChannel.write(sendByteBuffer);
        System.out.println("me : " + new String(sendByteBuffer.array()));
        int msgSize = 0;
        while (msgSize < 10) {
            ByteBuffer readByteBuffer = ByteBuffer.allocate(1024);
            int read = clientSocketChannel.read(readByteBuffer);
            String readStr = new String(readByteBuffer.array());
            if (read > 0) {
                System.out.println("robot : " + readStr);
                msgSize ++;
                ByteBuffer resByteBuffer = null;
                if (readStr.contains("hello")) {
                    resByteBuffer = ByteBuffer.wrap("how old are you?.".getBytes());
                    clientSocketChannel.write(resByteBuffer);
                    System.out.println("me : " + new String(resByteBuffer.array()));
                    resByteBuffer.clear();
                }
                if (readStr.contains("old")) {
                    resByteBuffer = ByteBuffer.wrap("en, place say hello!".getBytes());
                    clientSocketChannel.write(resByteBuffer);
                    System.out.println("me : " + new String(resByteBuffer.array()));
                    resByteBuffer.clear();
                }
            }
        }
        ByteBuffer resByteBuffer = ByteBuffer.wrap("bey bey!".getBytes());
        clientSocketChannel.write(resByteBuffer);
        System.out.println("me : " + new String(resByteBuffer.array()));
        resByteBuffer.clear();
        clientSocketChannel.close();
    }
}

NIO演示(Selector)

无Selector的NIO演示中,显然会出现空转的情况,以及无效连接的处理问题,这些问题都会影响性能。
NIO提供Selector多路复用器,优化上述问题
以下demo实现服务器与客户端通信,相互发消息。并由服务器转发给其他客户端(广播功能)

服务端类代码

server main类

import java.io.IOException;

public class NIOServerMain {
    public static void main(String[] args) throws IOException {
        NIOSelectorServer server = new NIOSelectorServer();
        server.start();
    }
}

server run类

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class NIOSelectorServer {

    public void start() throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8081));
        serverSocketChannel.configureBlocking(false);
        //注册到selector多路复用器中
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("server start...");
        run(selector);
    }

    /**
     * 遍历多路复用器的事件,处理事件
     */
    private void run(Selector selector) throws IOException {
        while (true) {
            //阻塞等待事件
            selector.select();

            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectedKey = iterator.next();
                try {
                    if (selectedKey.isAcceptable()) {
                        doAccept(selector, selectedKey);
                    }
                    if (selectedKey.isReadable()) {
                        doReadChannel(selectedKey, selector);
                    }
                } catch (IOException ioException) {
                    //有客户端断开连接
                    disConnect(selectedKey, "exception");
                }
                iterator.remove();
            }
        }
    }

    /**
     * 处理连接事件
     */
    private void doAccept(Selector selector, SelectionKey selectedKey) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel)selectedKey.channel();
        SocketChannel socketChannel = serverChannel.accept();
        socketChannel.configureBlocking(false);
        socketChannel.register(selector, SelectionKey.OP_READ);
        System.out.println(socketChannel.socket().getPort() + " connected");
    }

    /**
     * 处理接收信息事件
     */
    private void doReadChannel(SelectionKey selectedKey, Selector selector) throws IOException {
        SocketChannel channel = (SocketChannel)selectedKey.channel();
        ByteBuffer readByteBuffer = ByteBuffer.allocate(2048);
        int read = channel.read(readByteBuffer);
        String readStr = "";
        readByteBuffer.flip();
        readStr += StandardCharsets.UTF_8.decode(readByteBuffer);
        if (read > 0) {
            System.out.println(channel.socket().getPort() + " : " + readStr.length() + " - "+ readStr);
            //转发消息(其他客户端)
            broadcast(selectedKey, selector, readStr);
            if (readStr.contains("hello")) {
                sendMsg(channel, "hello! I am robot.");
            }
            if (readStr.contains("old")) {
                sendMsg(channel, "I am 1 years old.");
            }
            if (readStr.contains("bye")) {
                sendMsg(channel, "see you.");
            }
        }
        if (read == -1) {
            //有客户端断开连接
            disConnect(selectedKey, "read = -1");
        }
    }

    /**
     * 连接异常的处理
     */
    private void disConnect(SelectionKey selectedKey, String type) throws IOException {
        SocketChannel channel = (SocketChannel)selectedKey.channel();
        System.out.println(channel.socket().getPort() + " disconnected. " + type);
        selectedKey.cancel();
        channel.close();
    }

    /**
     * 发送消息
     */
    private void sendMsg(SocketChannel channel, String s) throws IOException {
        ByteBuffer sendByteBuffer = ByteBuffer.wrap(s.getBytes());
        channel.write(sendByteBuffer);
        System.out.println("me : " + new String(sendByteBuffer.array()));
    }

    /**
     * 广播
     * 转发消息(给其他客户端)
     */
    private void broadcast(SelectionKey  fromSelectedKey, Selector selector, String readStr) throws IOException {
        Iterator<SelectionKey> selectionKeyIterator = selector.keys().iterator();
        while (selectionKeyIterator.hasNext()) {
            SelectionKey otherKey = selectionKeyIterator.next();
            if (otherKey == fromSelectedKey) {
                continue;
            }
            if (!(otherKey.channel() instanceof SocketChannel)) {
                continue;
            }
            SocketChannel otherChannel = (SocketChannel)otherKey.channel();
            sendMsg(otherChannel, "(转发自 "+ ((SocketChannel)fromSelectedKey.channel()).socket().getPort() + ")" + readStr);
        }
    }
}

客户端代码

一共构造了两个客户端(消息客户端和looker客户端), looker客户端优先启动,随后启动消息客户端,消息客户端与服务器的通信会被转发给looker客户端

look client main类

import java.io.IOException;

public class NIOClientLookMain {
    public static void main(String[] args) throws IOException, InterruptedException {
        NIOSelectorClient client = new NIOSelectorLookClient();
        client.start(8081, 100);
    }
}

msg client main类

import java.io.IOException;

public class NIOClientMain {
    public static void main(String[] args) throws IOException, InterruptedException {
        NIOSelectorClient lookClient = new NIOSelectorClient();
        lookClient.start(8081, 10);
    }
}

client run类

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;

public class NIOSelectorClient {
    protected int port;
    protected int size;
    public void start(int port, int size) throws IOException, InterruptedException {
        this.port = port;
        this.size = size;
        SocketChannel clientSocketChannel = SocketChannel.open();
        clientSocketChannel.connect(new InetSocketAddress("127.0.0.1",port));
        clientSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        clientSocketChannel.register(selector, SelectionKey.OP_READ);
        //发送开始数据
        sendMsg(clientSocketChannel, "hello! I am client " + clientSocketChannel.socket().getLocalPort() + ".");
        run(selector);
        sendMsg(clientSocketChannel, "bye bye!");
        clientSocketChannel.close();
    }

    /**
     * 遍历多路复用器的事件,处理事件
     */
    protected void run(Selector selector) throws IOException, InterruptedException {
        int msgSize = 0;
        while (msgSize < size) {
            int length=selector.select();
            if(length ==0){
                continue;
            }
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while(iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if(selectionKey.isReadable()){
                    boolean readChannel = false;
                    try {
                        readChannel = doReadChannel(selectionKey, selector);
                    } catch (IOException e) {
                        selectionKey.cancel();
                        System.out.println("robot disconnect, restart connect...");
                        while (true){
                            try {
                                reConnect();
                                return;
                            } catch (IOException ioException) {
                                System.out.println("restart connecting(5s) ");
                                //ioException.printStackTrace();
                                Thread.sleep(5000);
                            }
                        }
                    }
                    if (readChannel) {
                        msgSize ++;
                    }
                }
                iterator.remove();
            }
        }
    }

    protected boolean doReadChannel(SelectionKey selectedKey, Selector selector) throws IOException {
        SocketChannel channel = (SocketChannel)selectedKey.channel();
        ByteBuffer readByteBuffer = ByteBuffer.allocate(2048);
        int read = channel.read(readByteBuffer);
        String readStr = "";
        readByteBuffer.flip();
        readStr += StandardCharsets.UTF_8.decode(readByteBuffer);
        if (read > 0) {
            System.out.println("robot : " + readStr);
            if (readStr.contains("hello")) {
                sendMsg(channel, "how old are you?.");
            }
            if (readStr.contains("old")) {
                sendMsg(channel, "en, place say hello!");
            }
            return true;
        }
        return false;
    }

    protected void sendMsg(SocketChannel channel, String sendStr) throws IOException {
        ByteBuffer sendByteBuffer = ByteBuffer.wrap(sendStr.getBytes());
        channel.write(sendByteBuffer);
        System.out.println("me : " + new String(sendByteBuffer.array()));
    }

    protected void reConnect() throws IOException, InterruptedException {
        NIOSelectorClient client = new NIOSelectorClient();
        client.start(port, size);
    }
}

look client run类

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;

public class NIOSelectorLookClient extends NIOSelectorClient{
    @Override
    public void start(int port, int size) throws IOException, InterruptedException {
        this.port = port;
        this.size = size;
        SocketChannel clientSocketChannel = SocketChannel.open();
        clientSocketChannel.connect(new InetSocketAddress("127.0.0.1",port));
        clientSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        clientSocketChannel.register(selector, SelectionKey.OP_READ);
        //发送开始数据
        sendMsg(clientSocketChannel, "I am looker. " + clientSocketChannel.socket().getLocalPort() + ".");
        run(selector);
    }

    @Override
    protected boolean doReadChannel(SelectionKey selectedKey, Selector selector) throws IOException {
        SocketChannel channel = (SocketChannel)selectedKey.channel();
        ByteBuffer readByteBuffer = ByteBuffer.allocate(2048);
        int read = channel.read(readByteBuffer);
        String readStr = "";
        readByteBuffer.flip();
        readStr += StandardCharsets.UTF_8.decode(readByteBuffer);
        if (read > 0) {
            System.out.println("robot : " + readStr.length() + " - "+ readStr);
            if (readStr.contains("bye")) {
                sendMsg(channel, "bye.");
            }
            return true;
        }
        return false;
    }

    @Override
    protected void reConnect() throws IOException, InterruptedException {
        NIOSelectorClient client = new NIOSelectorLookClient();
        client.start(port, size);
    }
}

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

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

相关文章

Go语言在机器学习中有未来吗?

Go 是一种开源编程语言&#xff0c;最初由 Google 设计&#xff0c;用于优化系统级服务的构建和使用、在大型代码库上轻松工作&#xff0c;以及利用多核联网机器。 Go 于 2009 年推出&#xff0c;作为一种静态类型和编译型编程语言&#xff0c;深受 C 语言的影响&#xff0c;注…

Prometheus + grafana 的监控平台部署

一、Prometheus安装 tar -zxvf prometheus-2.44.0.linux-amd64.tar.gz -C /opt/module/ sudo chown -R bigdata:bigdata /opt/module/prometheus-2.44.0.linux-amd64 mv /opt/module/prometheus-2.44.0.linux-amd64 /opt/module/prometheus-2.44.0 ln -s /opt/module/promethe…

【深入解析spring cloud gateway】02 网关路由断言

一、断言(Predicate)的意义 断言是路由配置的一部分&#xff0c;当断言条件满足&#xff0c;即执行Filter的逻辑&#xff0c;如下例所示 spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgpredicates:- Path/red/{segment}filters:- AddR…

OCELOT: Overlapped Cell on Tissue Dataset for Histopathology

OCELOT dataset D { ( x s , y s c , x l , y l t , c x , c y ) i } i 1 N \mathcal{D} \left\{\left(\mathbf{x}_s, \mathbf{y}_s^c, \mathbf{x}_l, \mathbf{y}_l^t, c_x, c_y\right)_i\right\}_{i1}^{N} D{(xs​,ysc​,xl​,ylt​,cx​,cy​)i​}i1N​ x s ∈ R 1024 1…

修复中间件log4j漏洞方案(直接更换漏洞jar包)

说明&#xff1a; 后台服务里面的log4j漏洞我们已经全部升级处理了&#xff0c;但是一些中间件镜像包里的log4j漏洞需要单独处理 解决办法以ElasticSearch7.6.2为例&#xff1a; 方法&#xff1a; &#xff08;1&#xff09;找到容器里面有哪些旧的log4j依赖包 &#xff08;…

023-从零搭建微服务-推送服务(三)

原【短信服务】更名【推送服务】 写在最前 如果这个项目让你有所收获&#xff0c;记得 Star 关注哦&#xff0c;这对我是非常不错的鼓励与支持。 源码地址&#xff08;后端&#xff09;&#xff1a;https://gitee.com/csps/mingyue 源码地址&#xff08;前端&#xff09;&a…

Java后端开发面试题——企业场景篇

单点登录这块怎么实现的 单点登录的英文名叫做&#xff1a;Single Sign On&#xff08;简称SSO&#xff09;,只需要登录一次&#xff0c;就可以访问所有信任的应用系统 JWT解决单点登录 用户访问其他系统&#xff0c;会在网关判断token是否有效 如果token无效则会返回401&am…

图神经网络和分子表征:4. PAINN

如果说 SchNet 带来了【3D】的火种&#xff0c;DimeNet 燃起了【几何】的火苗&#xff0c;那么 PAINN 则以星火燎原之势跨入 【等变】时代。 在 上一节 中&#xff0c;我们提到&#xff0c; PAINN 在看到 DimeNet 取得的成就之后&#xff0c;从另一个角度解决了三体几何问题&a…

css3对文字标签不同宽,不同高使用瀑布流对齐显示

<div class"wrapper" style"padding: 0;"><span class"wf-item task-tags text-center" v-for"(item,index) in data.categorys" :key"index">{{ item }}</span> </div>/* 名称瀑布流显示 */ .wrap…

基于PyTorch的交通标志目标检测系统

一、开发环境 Windows 10PyCharm 2021.3.2Python 3.7PyTorch 1.7.0 二、制作交通标志数据集&#xff0c;如下图 三、配置好数据集的地址&#xff0c;然后开始训练 python train.py --data traffic_data.yaml --cfg traffic_yolov5s.yaml --weights pretrained/yolov5s.pt --e…

嵌入式基础知识-DMA

本篇来介绍DMA的一些基础知识。 1 DMA简介 DMA&#xff08;Direct Memory Access&#xff09;,中文名为直接内存访问&#xff0c;它是一些计算机总线架构提供的功能&#xff0c;能使数据从附加设备&#xff08;如磁盘驱动器&#xff09;直接发送到计算机主板的内存上。对应嵌…

(笔记七)利用opencv进行形态学操作

&#xff08;1&#xff09;程序清单 形态学操作是一种图像处理技术&#xff0c;它基于数学形态学理论&#xff0c;用于改变图像的形状和结构。它主要通过结构元素的腐蚀和膨胀操作来实现。 #!/usr/bin/env python # -*- coding:utf-8 -*- """ author: LIFEI t…

2023-9-4 最大公约数

题目链接&#xff1a;最大公约数 #include <iostream>using namespace std;int gcd(int a, int b) {return b ? gcd(b, a % b) : a; }int main() {int n;cin >> n;while(n--){int a, b;cin >> a >> b;cout << gcd(a, b) << endl;}return …

uniapp 处理 分页请求

我的需求是手机上一个动态滚动列表&#xff0c;下拉到底部时&#xff0c;触发分页数据请求 uniapp上处理分页解决方案 主要看你是如何写出滚动条的。我想到的目前有三种 &#xff08;1&#xff09;页面滚动&#xff1a;直接使用onReachBottom方法&#xff0c;可以监听到达底部…

【python爬虫】16.爬虫知识点总结复习

文章目录 前言爬虫总复习工具解析与提取&#xff08;一&#xff09;解析与提取&#xff08;二&#xff09;更厉害的请求存储更多的爬虫更强大的爬虫——框架给爬虫加上翅膀 爬虫进阶路线指引解析与提取 存储数据分析与可视化更多的爬虫更强大的爬虫——框架项目训练 反爬虫应对…

8K视频来了,8K 视频编辑的最低系统要求

当今 RED、Canon、Ikegami、Sony 等公司的 8K 摄像机以及 8K 电视&#xff0c;许多视频内容制作人和电影制作人正在认真考虑 8K 拍摄、编辑和后期处理&#xff0c;需要什么样的系统来处理如此海量的数据&#xff1f; 中央处理器&#xff08;CPU&#xff09; 首先&#xff0c;…

Redis 集群环境案例安装步骤

1. 3主3从redis集群配置 1.1 找3台真实虚拟机&#xff0c;各自新建 mkdir -p /myredis/cluster 1.2 新建6个独立的redis实例服务 1.2.1 本次案例设计说明(ip有变化) https://processon.com/diagraming/5fe6d76ce401fd549c8fe708 1.2.2 IP: 192.168.111.175端门6381/端口6…

基于Matlab实现多个图像压缩案例(附上源码+数据集)

图像压缩是一种将图像数据量减少的技术&#xff0c;以减少存储空间和传输带宽的需求。在本文中&#xff0c;我们将介绍如何使用Matlab实现图像压缩。 文章目录 简单案例源码数据集下载 简单案例 首先&#xff0c;我们需要了解图像压缩的两种主要方法&#xff1a;有损压缩和无…

深入理解联邦学习——联邦学习的分类:基础知识

分类目录&#xff1a;《深入理解联邦学习》总目录 在实际中&#xff0c;孤岛数据具有不同分布特点&#xff0c;根据这些特点&#xff0c;我们可以提出相对应的联邦学习方案。下面&#xff0c;我们将以孤岛数据的分布特点为依据对联邦学习进行分类。 考虑有多个数据拥有方&…

[国产MCU]-W801开发实例-MQTT客户端通信

MQTT客户端通信 文章目录 MQTT客户端通信1、MQTT介绍2、W801的MQTT客户端相关API介绍3、代码实现本文将详细介绍如何在W801中使用MQTT协议通信。 1、MQTT介绍 MQTT 被称为消息队列遥测传输协议。它是一种轻量级消息传递协议,可通过简单的通信机制帮助资源受限的网络客户端。 …