Spark编程实验四:Spark Streaming编程

news2025/1/17 5:52:17

目录

一、目的与要求

二、实验内容

三、实验步骤

1、利用Spark Streaming对三种类型的基本数据源的数据进行处理

2、利用Spark Streaming对Kafka高级数据源的数据进行处理

3、完成DStream的两种有状态转换操作

4、把DStream的数据输出保存到文本文件或MySQL数据库中

四、结果分析与实验体会


一、目的与要求

1、通过实验掌握Spark Streaming的基本编程方法;
2、熟悉利用Spark Streaming处理来自不同数据源的数据。
3、熟悉DStream的各种转换操作。
4、熟悉把DStream的数据输出保存到文本文件或MySQL数据库中。

二、实验内容

1、参照教材示例,利用Spark Streaming对三种类型的基本数据源的数据进行处理。 
2、参照教材示例,完成kafka集群的配置,利用Spark Streaming对Kafka高级数据源的数据进行处理,注意topic为你的姓名全拼
3、参照教材示例,完成DStream的两种有状态转换操作。
4、参照教材示例,完成把DStream的数据输出保存到文本文件或MySQL数据库中。

三、实验步骤

1、利用Spark Streaming对三种类型的基本数据源的数据进行处理

(1)文件流

首先打开第一个终端作为数据流终端,创建一个logfile目录:

[root@bigdata zhc]# cd /home/zhc/mycode/sparkstreaming
[root@bigdata sparkstreaming]# mkdir logfile
[root@bigdata sparkstreaming]# cd logfile

然后打开第二个终端作为流计算终端,在“/logfile/”目录下面新建一个py程序:

[root@bigdata logfile]# vim FileStreaming.py

输入如下代码:

#/home/zhc/mycode/sparkstreaming/logfile/FileStreaming.py

from pyspark import SparkContext, SparkConf
from pyspark.streaming import StreamingContext

conf = SparkConf()
conf.setAppName('TestDStream')
conf.setMaster('local[2]')
sc = SparkContext(conf = conf)
ssc = StreamingContext(sc, 10)
lines = ssc.textFileStream('file:///home/zhc/mycode/sparkstreaming/logfile')
words = lines.flatMap(lambda line: line.split(' '))
wordCounts = words.map(lambda x : (x,1)).reduceByKey(lambda a,b:a+b)
wordCounts.pprint()
ssc.start()
ssc.awaitTermination()

保存该文件并执行如下命令:

[root@bigdata logfile]# spark-submit FileStreaming.py 

然后我们进入数据流终端,在logfile目录下新建一个log2.txt文件,然后往里面输入一些英文语句后保存退出,再次切换到流计算终端,就可以看见打印出单词统计信息了。

(2)套接字流

1)使用套接字流作为数据源

继续在流计算端的sparkstreaming目录下创建一个socket目录,然后在该目录下创建一个NetworkWordCount.py程序:

[root@bigdata sparkstreaming]# mkdir socket
[root@bigdata sparkstreaming]# cd socket
[root@bigdata socket]# vim NetworkWordCount.py

输入如下代码:

#/home/zhc/mycode/sparkstreaming/socket/NetworkWordCount.py

from __future__ import print_function
import sys
from pyspark import SparkContext
from pyspark.streaming import StreamingContext

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: NetworkWordCount.py <hostname> <port>", file=sys.stderr)
        exit(-1)
    sc = SparkContext(appName="PythonStreamingNetworkWordCount")
    ssc = StreamingContext(sc, 5)
    lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
    counts = lines.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).reduceByKey(lambda a, b: a+b)
    counts.pprint()
    ssc.start()
    ssc.awaitTermination()

再在数据流终端启动Socket服务器端:

[root@bigdata logfile]# nc -lk 9999

然后再进入流计算终端,执行如下代码启动流计算:

[root@bigdata socket]# spark-submit NetworkWordCount.py localhost 9999

然后在数据流终端内手动输入一行英文句子后回车,多输入几次,流计算终端就会不断执行词频统计并打印出信息。

2)使用Socket编程实现自定义数据源

下面我们再前进一步,把数据源头的产生方式修改一下,不要使用nc程序,而是采用自己编写的程序产生Socket数据源。在数据流终端执行以下命令,编写DataSourceSocket.py文件:

[root@bigdata logfile]# cd /home/zhc/mycode/sparkstreaming/socket
[root@bigdata socket]# vim DataSourceSocket.py

输入如下代码:

#/home/zhc/mycode/sparkstreaming/socket/DataSourceSocket.py
import socket
# 生成socket对象
server = socket.socket()
# 绑定ip和端口
server.bind(('localhost', 9999))
# 监听绑定的端口
server.listen(1)
while 1:
    # 为了方便识别,打印一个“我在等待”
    print("I'm waiting the connect...")
    # 这里用两个值接受,因为连接上之后使用的是客户端发来请求的这个实例
    # 所以下面的传输要使用conn实例操作
    conn,addr = server.accept()
    # 打印连接成功
    print("Connect success! Connection is from %s " % addr[0])
    # 打印正在发送数据
    print('Sending data...')
    conn.send('I love hadoop I love spark hadoop is good spark is fast'.encode())
    conn.close()
    print('Connection is broken.')

继续在数据流终端执行如下命令启动Socket服务端:

[root@bigdata socket]# spark-submit DataSourceSocket.py

再进入流计算终端,执行如下代码启动流计算:

[root@bigdata socket]# spark-submit NetworkWordCount.py localhost 9999

(3)RDD队列流

继续在sparkstreaming目录下新建rddqueue目录并在该目录下创建RDDQueueStream.py程序:

[root@bigdata sparkstreaming]# mkdir rddqueue
[root@bigdata sparkstreaming]# cd rddqueue
[root@bigdata rddqueue]# vim RDDQueueStream.py

输入如下代码:

#/home/zhc/mycode/sparkstreaming/rddqueue/RDDQueueStreaming.py
import time
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
    sc = SparkContext(appName="PythonStreamingQueueStream")
    ssc = StreamingContext(sc, 2)
    #创建一个队列,通过该队列可以把RDD推给一个RDD队列流
    rddQueue = []
    for i in range(5):
        rddQueue += [ssc.sparkContext.parallelize([j for j in range(1, 1001)], 10)]
        time.sleep(1)
    #创建一个RDD队列流
    inputStream = ssc.queueStream(rddQueue)
    mappedStream = inputStream.map(lambda x: (x % 10, 1))
    reducedStream = mappedStream.reduceByKey(lambda a, b: a + b)
    reducedStream.pprint()
    ssc.start()
    ssc.stop(stopSparkContext=True, stopGraceFully=True)

保存退出后,进入流计算终端再执行如下命令:

[root@bigdata rddqueue]# spark-submit RDDQueueStream.py

2、利用Spark Streaming对Kafka高级数据源的数据进行处理

此过程可以参照这篇博客的第四、五部分内容:

【数据采集与预处理】数据接入工具Kafka-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/Morse_Chen/article/details/135273370?spm=1001.2014.3001.5501

3、完成DStream的两种有状态转换操作

说明:上面的词频统计程序NetworkWordCount.py采取了无状态转换操作。

(1)滑动窗口转换操作

在socket目录下创建WindowedNetworkWordCount.py程序并输入如下代码:

#/home/zhc/mycode/sparkstreaming/socket/WindowedNetworkWordCount.py
from __future__ import print_function
import sys
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: WindowedNetworkWordCount.py <hostname> <port>", file=sys.stderr)
        exit(-1)
    sc = SparkContext(appName="PythonStreamingWindowedNetworkWordCount")
    ssc = StreamingContext(sc, 10)
    ssc.checkpoint("file:///home/zhc/mycode/sparkstreaming/socket/checkpoint")
    lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
    counts = lines.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).reduceByKeyAndWindow(lambda x, y: x + y, lambda x, y: x - y, 30, 10)
    counts.pprint()
    ssc.start()
    ssc.awaitTermination()

然后在数据流终端执执行如下命令运行nc程序:

[root@bigdata sparkstreaming]# cd /home/zhc/mycode/sparkstreaming/socket
[root@bigdata socket]# nc -lk 9999

然后再在流计算终端运行WindowedNetworkWordCount.py代码:

[root@bigdata socket]# spark-submit WindowedNetworkWordCount.py localhost 9999

这时,可以查看流计算终端内显示的词频动态统计结果,可以看到,随着时间的流逝,词频统计结果会发生动态变化。 

(2)updateStateByKey操作

在“/home/zhc/mycode/sparkstreaming/”路径下新建目录“/stateful”,并在该目录下新建代码文件NetworkWordCountStateful.py。

[root@bigdata sparkstreaming]# mkdir stateful
[root@bigdata sparkstreaming]# cd stateful
[root@bigdata stateful]# vim NetworkWordCountStateful.py

输入如下代码: 

#/home/zhc/mycode/sparkstreaming/stateful/NetworkWordCountStateful.py
from __future__ import print_function
import sys
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: NetworkWordCountStateful.py <hostname> <port>", file=sys.stderr)
        exit(-1)
    sc = SparkContext(appName="PythonStreamingStatefulNetworkWordCount")
    ssc = StreamingContext(sc, 1)
    ssc.checkpoint("file:///home/zhc/mycode/sparkstreaming/stateful/")           
    # RDD with initial state (key, value) pairs
    initialStateRDD = sc.parallelize([(u'hello', 1), (u'world', 1)]) 
    def updateFunc(new_values, last_sum):
        return sum(new_values) + (last_sum or 0) 
    lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
    running_counts = lines.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).updateStateByKey(updateFunc, initialRDD=initialStateRDD) 
    running_counts.pprint()
    ssc.start()
    ssc.awaitTermination()

在“数据源终端”,执行如下命令启动nc程序:

[root@bigdata stateful]# nc  -lk  9999

在“流计算终端”,执行如下命令提交运行程序:

[root@bigdata stateful]# spark-submit NetworkWordCountStateful.py localhost 9999

在数据源终端内手动输入一些单词并回车,再切换到流计算终端,可以看到已经输出了类似如下的词频统计信息: 

4、把DStream的数据输出保存到文本文件或MySQL数据库中

(1)把DStream输出到文本文件中

在stateful目录下新建NetworkWordCountStatefulText.py文件:

[root@bigdata stateful]# vim NetworkWordCountStatefulText.py

输入如下代码: 

#/home/zhc/mycode/sparkstreaming/stateful/NetworkWordCountStatefulText.py
from __future__ import print_function
import sys
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: NetworkWordCountStateful.py <hostname> <port>", file=sys.stderr)
        exit(-1)
    sc = SparkContext(appName="PythonStreamingStatefulNetworkWordCount")
    ssc = StreamingContext(sc, 1)
    ssc.checkpoint("file:///home/zhc/mycode/sparkstreaming/stateful/statefultext")
    # RDD with initial state (key, value) pairs
    initialStateRDD = sc.parallelize([(u'hello', 1), (u'world', 1)])
    def updateFunc(new_values, last_sum):
        return sum(new_values) + (last_sum or 0)
    lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
    running_counts = lines.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).updateStateByKey(updateFunc, initialRDD=initialStateRDD)
    running_counts.saveAsTextFiles("file:///home/zhc/mycode/sparkstreaming/stateful/statefultext/output")
    running_counts.pprint()
    ssc.start()
    ssc.awaitTermination()

在“数据源终端”,执行如下命令启动nc程序:

[root@bigdata stateful]# nc  -lk  9999

在“流计算终端”,执行如下命令提交运行程序:

[root@bigdata stateful]# spark-submit NetworkWordCountStatefulText.py localhost 9999

在数据源终端内手动输入一些单词并回车,再切换到流计算终端,可以看到已经输出了类似如下的词频统计信息:  

在“/home/zhc/mycode/sparkstreaming/stateful/statefultext”目录下便可查看到如下输出目录结果:

进入某个目录下,就可以看到类似part-00000的文件,里面包含了流计算过程的输出结果。

(2)把DStream写入到MySQL数据库中

首先启动MySQL数据库:

[root@bigdata stateful]# systemctl start mysqld.service
[root@bigdata stateful]# mysql -u root -p

然后创建spark数据库和wordcount表:

mysql> use spark;
mysql> create table wordcount (word char(20), count int(4));

然后再在终端安装python连接MySQL的模块:

[root@bigdata stateful]# pip3 install PyMySQL

在stateful目录并在该目录下创建NetworkWordCountStatefulDB.py文件: 

[root@bigdata stateful]# vim NetworkWordCountStatefulDB.py

输入如下代码: 

#/home/zhc/mycode/sparkstreaming/stateful/NetworkWordCountStatefulDB.py
from __future__ import print_function 
import sys 
import pymysql 
from pyspark import SparkContext
from pyspark.streaming import StreamingContext 
if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Usage: NetworkWordCountStateful <hostname> <port>", file=sys.stderr)
        exit(-1)
    sc = SparkContext(appName="PythonStreamingStatefulNetworkWordCount")
    ssc = StreamingContext(sc, 1)
    ssc.checkpoint("file:///home/zhc/mycode/sparkstreaming/stateful/statefuldb")  
    # RDD with initial state (key, value) pairs
    initialStateRDD = sc.parallelize([(u'hello', 1), (u'world', 1)]) 
    def updateFunc(new_values, last_sum):
        return sum(new_values) + (last_sum or 0) 
    lines = ssc.socketTextStream(sys.argv[1], int(sys.argv[2]))
    running_counts = lines.flatMap(lambda line: line.split(" ")).map(lambda word: (word, 1)).updateStateByKey(updateFunc, initialRDD=initialStateRDD) 
    running_counts.pprint() 
    def dbfunc(records):
        db = pymysql.connect(host="localhost",user="root",password="MYsql123!",database="spark")
        cursor = db.cursor() 
        def doinsert(p):
            sql = "insert into wordcount(word,count) values ('%s', '%s')" % (str(p[0]), str(p[1]))
            try:
                cursor.execute(sql)
                db.commit()
            except:
                db.rollback()
        for item in records:
            doinsert(item) 
    def func(rdd):
        repartitionedRDD = rdd.repartition(3)
        repartitionedRDD.foreachPartition(dbfunc)
    running_counts.foreachRDD(func)
    ssc.start()
    ssc.awaitTermination()

在“数据源终端”,执行如下命令启动nc程序:

[root@bigdata stateful]# nc  -lk  9999

在“流计算终端”,执行如下命令提交运行程序:

[root@bigdata stateful]# spark-submit NetworkWordCountStatefulDB.py localhost 9999

在数据源终端内手动输入一些单词并回车,再切换到流计算终端,可以看到已经输出了类似如下的词频统计信息:

 

到MySQL终端便可以查看wordcount表中的内容:

mysql> select * from wordcount;

.......

四、结果分析与实验体会

        Spark Streaming是一个用于实时数据处理的流式计算框架,它基于 Apache Spark 平台,提供了高可靠性、高吞吐量和容错性强等特点。在进行 Spark Streaming 编程的实验中,掌握了Spark Streaming的基本编程方法;能够利用Spark Streaming处理来自不同数据源的数据以及DStream的各种转换操作;把DStream的数据输出保存到文本文件或MySQL数据库中。
        理解DStream:DStream 是 Spark Streaming 的核心概念,代表连续的数据流。在编程时,我们可以通过输入源(比如 Kafka、Flume、HDFS)创建一个 DStream 对象,并对其进行转换和操作。需要注意的是,DStream 是以时间片为单位组织数据的,因此在编写代码时要考虑时间窗口的大小和滑动间隔。
        适当设置批处理时间间隔:批处理时间间隔决定了 Spark Streaming 处理数据的粒度,过小的时间间隔可能导致频繁的任务调度和资源开销,而过大的时间间隔则可能造成数据处理延迟。因此,在实验中需要根据具体场景和需求来选择合适的时间间隔。
        使用合适的转换操作:Spark Streaming 提供了丰富的转换操作,如 map、flatMap、filter、reduceByKey 等,可以实现对数据流的转换和处理。在实验中,需要根据具体业务逻辑和需求选择合适的转换操作,并合理组合这些操作,以获取期望的结果。
        考虑容错性和数据丢失:Spark Streaming 具备很好的容错性,可以通过记录数据流的偏移量来保证数据不会丢失。在实验中,需要注意配置合适的容错机制,确保数据处理过程中的异常情况能够被恢复,并尽量避免数据丢失。
        优化性能和资源利用:对于大规模的实时数据处理任务,性能和资源利用是非常重要的。在实验中,可以通过调整并行度、合理设置缓存策略、使用广播变量等手段来提高性能和资源利用效率。
        总的来说,Spark Streaming 是一个功能强大且易用的流式计算框架,通过合理使用其提供的特性和操作,可以实现各种实时数据处理需求。在实验中,需要深入理解其原理和机制,并根据具体需求进行合理配置和优化,以获得良好的性能和结果。

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

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

相关文章

uniapp中uview组件库的丰富Upload 上传上午用法

目录 基础用法 #上传视频 #文件预览 #隐藏上传按钮 #限制上传数量 #自定义上传样式 API #Props #Methods #Slot #Events 基础用法 可以通过设置fileList参数(数组&#xff0c;元素为对象)&#xff0c;显示预置的图片。其中元素的url属性为图片路径 <template>…

【VSCode】关闭双击shift出现搜索

原因 有时候总是手滑按两下shift&#xff0c;每次都会弹出如下图的搜索框&#xff0c;导致很不方便 解决办法 找到该文件 C:\Users\admin\.vscode\extensions\k--kato.intellij-idea-keybindings-1.5.12\package.json&#xff08;admin是自己的用户名&#xff09; 然后关键字…

java go c++ 开源全文搜索引擎

Apache Lucene Java 全文搜索框架 许可证&#xff1a;Apache-2.0 开发语言&#xff1a;Java 官网&#xff1a;https://lucene.apache.org/ Apache Lucene 是完全用 Java 编写的高性能、功能齐全的全文检索引擎架构&#xff0c;提供了完整的查询引擎和索引引擎、部分文本分析引…

python+django高校教材共享管理系统PyCharm 项目

本中原工学院教材共享平台采用的数据库是mysql&#xff0c;使用nodejs技术开发。在设计过程中&#xff0c;充分保证了系统代码的良好可读性、实用性、易扩展性、通用性、便于后期维护、操作方便以及页面简洁等特点。系统所要实现的功能分析&#xff0c;对于现在网络方便的管理&…

Cisco模拟器-跨交换机实现VLAN

计要求将两台相互连接的交换机上的VLAN号全局使用&#xff0c;技术上可以使用TRUNK技术的数据包标记功能来实现。 通过设计&#xff0c;可以对多台交换机进行整合&#xff0c;提高网络设备的利用率、降低网络工程的成本&#xff0c;同时也可以简化网络配置。 交换机0配置&…

从0开始界面设计师 Qt Designer

QT程序界面的 一个个窗口、控件&#xff0c;就是像上面那样用相应的代码创建出来的。 但是&#xff0c;把你的脑海里的界面&#xff0c;用代码直接写出来&#xff0c;是有些困难的。 很多时候&#xff0c;运行时呈现的样子&#xff0c;不是我们要的。我们经常还要修改代码调整界…

超维空间S2无人机使用说明书——52、初级版——使用PID算法进行基于yolo的目标跟踪

引言&#xff1a;在实际工程项目中&#xff0c;为了提高系统的响应速度和稳定性&#xff0c;往往需要采用一定的控制算法进行目标跟踪。这里抛砖引玉&#xff0c;仅采用简单的PID算法进行目标的跟随控制&#xff0c;目标的识别依然采用yolo。对系统要求更高的&#xff0c;可以对…

普中STM32-PZ6806L开发板(HAL库函数实现-USART2 中断接收)

简介 实现USART2 的 中断接收&#xff0c; 发送数据。电路原理图 USART2接线 原理图USART2 在主芯片引脚 实物图 其他知识 APIs stm32f1xx_hal_uart.h /* 堵塞发送, pData是发送数据, Size发送数据大小, Timeout是超时时间 */ HAL_StatusTypeDef HAL_UART_Transmit(UAR…

集合基础知识点

集合基础 1. 集合的由来 当 Java 程序中需要存放数据的时候&#xff0c;通常会定义变量来实现数据的存储&#xff0c;但是&#xff0c;当需要存储大量数据的时候该怎么办呢&#xff1f;这时首先想到的是数组&#xff0c;但是&#xff01;数组只能存放同一类型的数据&#xff…

react+redux+antd-mobile 之 记账本案例

1.环境搭建 //使用CRA创建项目&#xff0c;并安装必要依赖&#xff0c;包括下列基础包 //1. Redux状态管理 - reduxjs/toolkit 、 react-redux //2. 路由 - react-router-dom //3. 时间处理 - dayjs //4. class类名处理 - classnames //5. 移动端组件库 - antd-mobile //6. 请…

宝塔部署flask添加ssl即https

在宝塔部署flask的步骤我已经写了一篇博客:宝塔部署flask项目-CSDN博客 之前说如果出现找不到application错误: spawned uWSGI http 1 (pid: 3116) --- no python application found, check your startup logs for errors --- [pid: 3114|app: -1|req: -1/1] 127.0.0.1 () {6…

DockerCompose - 容器编排、模板命令、compose命令、Pottainer 可视化界面管理(一文通关)

目录 一、DockerCompose 容器编排 1.1、简介 1.2、Docker-Compose 安装 1.2.1、在线安装 1.2.2、离线安装 1.3、docker-compose.yml 中的模板命令 前置说明 模板命令 1.4、DockerCompse 命令 前置说明 up down exec ps restart rm top pause暂停 和 unpause恢…

【unity中使用高度图创建地图】

unity中使用高度图创建地图 插件 讲解案例为unity2022版本 这个是插件地址 也可以在资源商店中搜索 terrain-tools 介绍 Terrain Tools入门Terrain Tools是一个软件包&#xff0c;你可以选择将其添加到Unity 2019.1或更高版本中的任何项目中。要将该软件包添加到你的项目…

python+django校园篮球论坛交流系统v5re9

本课题使用Python语言进行开发。基于web,代码层面的操作主要在PyCharm中进行&#xff0c;将系统所使用到的表以及数据存储到MySQL数据库中 技术栈 系统权限按管理员和用户这两类涉及用户划分。 (a) 管理员&#xff1b;管理员使用本系统涉到的功能主要有&#xff1a;首页、个人中…

dash 中的模式匹配回调函数Pattern-Matching Callbacks 8

模式匹配 模式匹配回调选择器 MATCH、ALL 和 ALLSMALLER 允许您编写可以响应或更新任意或动态数量组件的回调函数。 此示例呈现任意数量的 dcc. Dropdown 元素&#xff0c;并且只要任何 dcc. Dropdown 元素发生更改&#xff0c;就会触发回调。尝试添加几个下拉菜单并选择它们的…

56.网游逆向分析与插件开发-游戏增加自动化助手接口-通过UI分析自动药水设定功能

内容来源于&#xff1a;易道云信息技术研究院VIP课 上一节内容&#xff1a;自动药水设定功能的逆向分析-CSDN博客 这次是假设没有之前的思路积累的话&#xff0c;怎样去找按钮事件。 通过ui当做切入点去做&#xff0c;就是一个窗口它显示不显示&#xff0c;游戏怎样控制这个…

【owt-server】一些构建项目梳理

【owt-server】清理日志&#xff1a;owt、srs、ffmpeg 【owt】p2p client mfc 工程梳理【m98】webrtc vs2017构建带符号的debug库【OWT】梳理构建的webrtc和owt mfc工程 m79的mfc客户端及owt-client

【PyQt】(自定义类)QIcon派生,更易用的纯色Icon

嫌Qt自带的icon太丑&#xff0c;自己写了一个&#xff0c;主要用于纯色图标的自由改色。 当然&#xff0c;图标素材得网上找。 Qt原生图标与现代图标对比&#xff1a; 没有对比就没有伤害 Qt图标 网络素材图标 自定义类XJQ_Icon&#xff1a; from PyQt5.QtGui import QIc…

数字PID算法基础

数字PID是由编程语言实现的PID算法并烧录到控制芯片中&#xff0c;控制芯片与电机驱动连接&#xff0c;将PID控制算法的输出转换为PWM控制信号发送给电机驱动电路&#xff0c;电机驱动电路与直流电机相连并将PWM控制信号转换为具有相同占空比的PWM供电电压&#xff0c;通过对输…

MacBook查看本机IP

嘚吧嘚 其实这也不是什么困难的问题&#xff0c;但是今年刚刚入坑Mac&#xff0c;外加用的频率不是很高&#xff0c;每次使用的时候都查&#xff0c;用完就忘&#xff0c;下次用的时候再查&#x1f92e;。真的把自己恶心坏了&#x1f648;。 所以写篇文章记录一下&#x1f92…