计算机网络背景 网络,是我们通信的重要媒介,在我们之前的学习当中,所有的操作都只是在局部单机进程进行通信,数据交流的,而网络则是可以完成计算机与计算机之间的通信
事实上在网络出现之前,计算机是用来计算导弹轨迹的,计算机可以提高我们的计算效率,但是随着计算量的增加,单一计算机已经不能满足计算需求了,需要计算机与计算机之间的通信,如果计算机与计算机通过人来进行通信的话效率太低了,且可能出错,所以我们由此出现了计算机网络,来实现计算机与计算机之间的通信
独立模式: 计算机之间相互独立 网络互联: 多台计算机连接在一起, 完成数据共享 局域网LAN: 计算机数量更多了, 通过交换机和路由器连接在一起 广域网WAN: 将远隔千里的计算机都连在一起 我们可以发现,网络的发展是随着距离越来越远的,在局域网内我们可以通过交换机来进行通信,距离更远时我们可以通过路由器来完成,随着一张路由器网遍布在我们所生活的世界中,我们便完成了远距离通信
注意:局域网与广域网只是相对的概念,地区与地区间可以看作广域网,而相对于更大的范围--国家之间,他们也就相当于局域网了
而我们不仅不同的主机之间需要有网络来传输数据,我们一台主机的内部,硬件与硬件之间,也是需要数据的传输的,同样也需要网络
协议 协议,其实就是一种约定
计算机之间的传输媒介是光信号和电信号 . 通过 " 频率 " 和 " 强弱 " 来表示 0 和 1 这样的信息 . 要想传递各种不同的信息, 就需要约定好双方的数据格式 . 我们举个通俗易懂的例子,四川人说话,陕西人听不懂,那么我们如果想让这两个人完成通信,他们之间就可以约定,都说普通话,这就是协议
计算机生产厂商有很多 ; 计算机操作系统 , 也有很多 ; 计算机网络硬件设备 , 还是有很多 ; 如何让这些不同厂商之间生产的计算机能够相互顺畅的通信 ? 就需要有人站出来 , 约定一个共同的标准 , 大家都来遵守 , 这就是 网络协议 网络协议 有了协议的基本认识,我们来看看在计算机内部,我们的数据是如何通过协议在两个主机之间进行传输的呢?
我们在操作系统中有各种各样的协议,需要进行管理,所以我们的操作系统通过结构体将这些协议组织起来,当一台主机需要发送数据到另一台主机时,需要将数据与协议进行合并,一同发送出去,所以我们真正进行数据传输时,大小会大一些,大的这部分就是协议,而后目标主机接收到数据,先对其按照特定的协议方式进行“拆包”,随后拿到数据传给上层
注意:两个主机之间需要进行协议的约定,都采用同一种方式对数据进行装包与拆包,若两个主机之间的协议不一致,则无法完成数据的传输,所以约定网络协议是很有必要的
网络里的协议就是一种数据格式,规定的相同的数据格式就是网络协议
协议分层 我们用一个经典的例子来对协议的分层进行形象化的描述,两个人需要交流,约定好都使用中文,这就是应用层的“协议”,电话机与电话机之间,约定好使用电话机协议进行数据的传输,这就是通信设备层的“协议”,再分别通过各自的接口来完成两个人的通信,那么我们如果想切换协议,两个人改成英文交流,此时我们只需要让应用层的用户改变说话的语言即可,对通信层没有影响,若想改变通信层的协议,改成使用手机而不是电话来进行通信,我们也只需要改变下层通信协议即可,不会对应用层造成影响
在这个例子中,其实我们就完成了对协议的分层,分为用户与通信方式之间,这样做的好处是完成了解耦,封装了层级之间的协议,当一层受影响时不会对其他层有影响
OSI七层模型 OSI ( Open System Interconnection ,开放系统互连)七层网络模型称为开放式系统互联参考模型,是一个逻辑上的定义和规范; 把网络从逻辑上分为了 7 层 .
call、apply、bind三者均能改变当前this指向
三者的区别:
三者的第一个参数均为新的this指向第二个参数:call和bind为参数列表,apply为参数数组只有bind返回一个函数 手写实现call函数
Function.prototype.TestCall = function(thisArg,arg){ //获取要执行的函数 let fn = this; //转换新this指向的类型 thisArg = (thisArg !== null && thisArg !==undefiend) ? Object(thisArg) : window; thisArg.fn = fn; //将函数执行的结果保存 let result = thisArg.fn(...arg); //删除 delete thisArg.fn; //返回函数执行的结果 return result; } 手写实现apply函数
Function.prototype.TestApply = function(thisArg, arrArg){ let fn = this; thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window; thisArg.fn = fn; //arrArg = arrArg ? arrArg : []; arrArg = arrArg || []; let result = thisArg.
1.首先需要确认自己的Ubuntu里有没有安装好的screen,如果遇到错误bash: screen: command not found,那就是说明没有安装.
2.安装screen:命令行中输入`apt-get install screen
权限不够,接下来进入root账户,以root用户运行:
认证失败,是因为我的Ubuntu账户之前没有开启root账户,接下来开启root账户:
参考链接:(2条消息) Ubuntu如何开启root账户登录_亲亲Friends的博客-CSDN博客
【注】Ubuntu默认不开启root账户是一种保护机制,尤其保护小白用户。在非root账户里,至少你用sudo激情删库之前,系统还要你输个密码冷静一下;如果登入了root账户,删系统关键文件的前后,可能得不到任何提示,系统当即崩溃(或者重启崩溃)是很危险的事情。所以root账户能不开就不开,强烈推荐等你对系统有充分了解并且熟知各项命令之后再开。
Step1:
设置root账户密码
Step2:
进入root账户
Step3:
安装screen
更新包
退出root账户
3.screen安装之后,在终端输入 screen 就可以新建一个新的终端了
这里还需要重新输入安装的命令
一、安装JAVA JDK 1、下载安装包
http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
注意:根据32/64位操作系统下载对应的安装包
2、添加系统变量:JAVA_HOME=C:\Program Files (x86)\Java\jdk1.8.0_14
二、安装ZooKeeper 1、下载安装包Apache ZooKeeper
2、 解压并进入ZooKeeper目录,如:D:\Kafka\zookeeper-3.4.9\conf, 将“zoo_sample.cfg”重命名为“zoo.cfg”,
3、打开“zoo.cfg”找到并编辑数据存放位置 dataDir=F:\\HC\\apache-zookeeper-3.7.0\\data(必须以\\分割)
4、在zoo.cfg文件中修改默认的Zookeeper端口(默认端口2181)
5、添加系统变量:ZOOKEEPER_HOME=D:\Kafka\zookeeper-3.4.9
6、编辑path系统变量,添加路径:%ZOOKEEPER_HOME%\bin
7、打开新的cmd,输入“zkServer“,运行Zookeeper
命令行提示如下:说明本地Zookeeper启动成功
注意:不要关了这个服务窗口 三、安装Kafka 1、 下载安装包
Apache Kafka
注意要下载二进制版本
2、 解压并进入Kafka目录,笔者:D:\Kafka\kafka_2.12-0.11.0.0
3、 进入config目录找到文件server.properties并打开
4、 找到并编辑日志保存的位置 log.dirs=F:\\HC\\kafka_2.13-2.8.1\\kafka-logs
5、 找到并编辑zookeeper.connect=localhost:2181
6、 Kafka会按照默认,在9092端口上运行,并连接zookeeper的默认端口:2181
7、 进入Kafka安装目录D:\Kafka\kafka_2.12-0.11.0.0,按下Shift+右键,选择“打开命令窗口”选项,打开命令行,输入:
.\bin\windows\kafka-server-start.bat .\config\server.properties 或bin\kafka-server-start.sh config\server.properties 注意:注意:不要关了这个窗口,启用Kafka前请确保ZooKeeper实例已经准备好并开始运行 四、测试 (linux直接在bin目录下.sh,windows需要进入bin\winndows下的.bat)
1、 创建主题,
进入Kafka安装目录D:\Kafka\kafka_2.12-0.11.0.0,按下Shift+右键,选择“打开命令窗口”选项,打开命令行,输入:
.\bin\windows\kafka-topics.bat --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test 2、查看主题输入:
.\bin\windows\kafka-topics.bat --list --zookeeper localhost:2181 3、 创建生产者,
进入Kafka安装目录D:\Kafka\kafka_2.12-0.11.0.0,按下Shift+右键,选择“打开命令窗口”选项,打开命令行,输入:
文章目录
1. LAN8720A简介
2. PHYAD[0]: PHY地址配置
3. MODE[2:0]: Mode配置
4. nINTSEL: nINT/REFCLKO配置
5. REGOFF: 配置内部+1.2V电压源
6.SMI(MDC/MDIO)总线接口介绍
6.1 MDIO接口
6.2 MDIO数据传输协议
7. 相关寄存器描述
8. 参考资料
1. LAN8720A简介
LAN8720A 是 SMSC 公司(已被 Microchip公司收购)设计的一个体积小、功耗低、全能型 10/100Mbps 的以太网物理层收发器。它是针对消费类电子和企业应用而设计的。LAN8720A总共只有 24Pin,仅支持 RMII接口。由它组成的网络结构如下图所示:
LAN8720A 通过 RMII与 MAC连接。RJ45是网络插座,在与 LAN8720A 连接之间还需要一个变压器,所以一般使用带电压转换和 LED 指示灯的 HY911105A型号的插座。一般来说,必须为使用 RMII接口的 PHY提供 50MHz的时钟源输入到 REF_CLK引脚,不过LAN8720A内部集成 PLL,可以将 25MHz的时钟源陪频到 50MHz 并在指定引脚输出该时钟,所以我们可以直接使其与 REF_CLK连接达到提供 50MHz时钟的效果。
LAN8720A 内部系统结构如下图所示:
LAN8720A 有各个不同功能模块组成,最重要的是数据接收控制器和发送控制器,其它的基本上都是与外部引脚挂钩,实现信号传输。部分引脚是具有双重功能的,比如PHYAD0与 RXER 引脚是共用的,在系统上电后 LAN8720A 会马上读取这部分共用引脚的电平,以确定系统的状态并保存在相关寄存器内,之后则自动转入作为另一功能引脚。
2. PHYAD[0]: PHY地址配置
PHYAD[0]引脚用于配置 SMI通信的 LAN8720A 地址,在芯片内部该引脚已经自带下拉电阻,默认认为 0(即使外部悬空不接),在系统上电时会检测该引脚获取得到 LAN8720A的地址为 0 或者 1,并保存在特殊模式寄存器(R18)的 PHYAD位中,该寄存器的 PHYAD有 5个位,在需要超过 2个 LAN8720A 时可以通过软件设置不同 SMI通信地址。
1.【运行】- 【打开配置】
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: 当前文件",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"cwd": "${fileDirname}"
}
]
}
2.python 代码 import sys
sys.path.append(".")
vue3.0如何使用富文本编译器,我在网上找了很多都是基于2.0的 很多3.0引入都不一样。搞了很半天。 发现了 VueQuill 很好用
下面是 使用方法 简单粗暴
效果图:
引入 npm install @vueup/vue-quill@alpha --save
这里有个坑:: npm 的时候要用cmd去下载 不然会报不识别符号,的奇奇怪怪的问题
然后就是 引入了:
import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css';
app.component('QuillEditor', QuillEditor)
使用(我这里直接封装成了组件):
<template> <div> <quill-editor theme="snow" contentType="html" enable :content="content" @textChange="textChange"></quill-editor> </div> </template> <script> export default { data() { return { content: `<p></p><p><br></p><ol><li><strong><em>我是大哥大.</em></strong></li><li><strong><em>疾风剑豪</em></strong></li><li><strong><em>嘉文四世</em></strong></li><li><strong><em>潮汐海灵</em></strong></li><li><strong><em>24635</em></strong></li></ol>` } }, methods: { textChange(e) { console.log(e, '98'); } } } </script> theme=“snow” 主题颜色
contentType=“html” 支持html类型
@textChange 事件
最近的要用到CSV格式的数据,所以这篇文章讲述一下QT读取CSV文件数据 。
xls文件是Excel电子表格的文件格式,而csv是一种比较通用的文件格式,xls文件只能用Excel才能打开,而csv文件可以用Excel、记事本、文本编辑器打开。
记住:CSV文件数据项使用“,”来分割的。
代码如下:
写入数据
//打开.csv文件 QFile file("200000.csv"); if(!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug()<<"Cannot open file for writing"; return; } QTextStream out(&file); //创建表头 out << tr("信息,") << tr("数字,") <<"\n"; //写入内容 for(int i = 0; i < 10; i++) { out << "test" << "," << i << "\n"; } //关闭文件 file.close(); 读取数据
QFile file("20000.csv"); /*如果以ReadWrite方式打开,不会把所有数据清除,若文件原来的长度为100字节,写操作写入了30字节,那还剩余70字节,并且这70字节和文件打开之前保持一致*/ if(!file.open(QIODevice::ReadOnly)) { qDebug()<<"请正确选择csv文件"; return; } QTextStream * read = new QTextStream(&file); QStringList Data = read->readAll().
首先更新相关的package: sudo apt-get update sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev 编译OpenCV需要用到下面的一些package:
GCC
CMake
GTK+2.x or higher
pkg-config
ffmpeg or libav development packages: libavcodec-dev, libavformat-dev, libswscale-dev
2. 下载python
Ubuntu默认带了各个版本的python
3. 下载OpenCV的源码
OpenCV官网上有linux版本的源码包可以下载,不过最好是从git上下载,这样可以保证下载得到的是最新的代码:
wget -O opencv.zip https://github.com/Itseez/opencv/archive/3.2.0.zip unzip opencv.zip 编译安装
进入到OpenCV的文件夹中,创建一个build目录,进行编译: cd opencv-3.2.0 mkdir build cd build cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local .. make sudo make install 测试OpenCV
输入命令如下: mkdir opencv-test cd opencv-test gedit DisplayImage.cpp 编辑如下代码:
第一步:安装commitizen 使用commitizen提交时,会提示你在commit时填写所有必需的提交字段,无需再等待git commit 钩子运行就可以拒绝你的commit。
全局安装commitizen
npm install commitizen -g 如果命令行直接输入cz没有出现如下内容的话,需要再运行下面的命令
// npm使用如下命令 commitizen init cz-conventional-changelog --save-dev --save-exact // yarn使用如下命令 commitizen init cz-conventional-changelog --yarn --dev --exact 这个时候,就在命令行使用 git cz 或 git-cz 或 cz 来提交代码了。
如果想在本项目下使用npm commit提交代码,需要再package.json中添加如下配置
"scripts": { "commit": "cz" } 注意:npm 6及以上版本
第二步:安装commitlint 安装commitizen后,使用git commit仍旧可以进行不规范的提交。而commitlint结合husky可以在提交不规范内容时会导致失败,并提示错误
安装commitlintnpm install -g @commitlint/cli @commitlint/config-conventional 生成配置文件。@commitlint/config-conventional是共享的commitlint配置,也可以使用其他的或者自定义的配置,我这里使用的是@commitlint/config-conventional。
使用cmd执行命令时,生成的commitlint.config.js文件内容是字符串,把前后的双引号去掉就可以了echo "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js 生成的commitlint.config.js文件内容如下:module.exports = {extends: ['@commitlint/config-conventional']} 第三步:安装Husky Husky 支持所有 Git 钩子,可以在合适的钩子中运行测试、格式化代码、验证commit信息是否符合规范
安装Husky
npx husky-init && npm install # npm npx husky-init && yarn # Yarn 1 yarn dlx husky-init --yarn2 && yarn # Yarn 2 此命令将在项目根目录下生成一个.
ansible加密模块ansible-vault ansible-vault简介在配置文件中指定密码文件路径创建加密文件修改加密文件的密码编辑加密文件查看加密文件将文件加密解密文件将文件解密解密文件并保留原加密文件 非交互式加密解密--指定密码文件指定密码文件加密数据指定密码文件查看数据指定密码文件解密数据 运行加密的playbook提示输入密码来运行playbook指定密码文件来运行加密playbook调用多个加密变量文件时输入多个密码/加载多个密码文件 RH294课程ansible-vault练习开启对应章节的练习环境完成本章练习 ansible-vault简介 为了配置被管理主机, ansible可能会使用一些敏感数据,比如密码或者api密钥。通常来说,这些以明的形式成 Inventory件或者ansible文件中。这种情况,任何用户访问了这些文件,都能看到敏感数据,非常不安全.
ansible vault是 ansible的组件,可以加密解密 ansible使用的数据。为了安全建议使用 ansible vault.
你可以使用 ansible-vault来创建,编辑,加密或解密或者查看文件。 ansible vault可以加密任何结构的数据。可以加密 nventory变量,定义变量的 playbook文件,传递到 playbook中的变量文件,或者 ansible role中的变量。
通常情况下,生产环境只使用ansible-vault来加密变量文件.
在配置文件中指定密码文件路径 # 编辑配置文件 vim ansible.cfg # 指定密码密码文件路径 [defaults] vault_password_file = /path/to/vault_password_file 创建加密文件 # 创建加密文件 [student@workstation data-variables]$ ansible-vault create test.yml New Vault password: # 输入文件密码 Confirm New Vault password: # 输入确认密码 # 输入完密码后就进入了编辑界面,想vim一样正常编辑即可. # 查看文件,发现文件已经被加密了 [student@workstation data-variables]$ cat test.yml $ANSIBLE_VAULT;1.1;AES256 37393965386233633466663233376436356238303931313262373730623663376161376631623231 6339313134366265346231363962326335663866323432340a633661653161646264633235313939 61303431653734663330613766373531323836396264636638313933663733356636613161356434 6464313964373464330a346565313434623137376331376431353737646563386637613832623031 65316336663238613664323233386332613035396234666161373964343934653131393438613665 65303261343462393538343332356136386164666430396632333230646138376163666564623064 39616234616462623837396435366438663266343333333735626430356435316362653763653235 36323630303634656235 修改加密文件的密码 # 修改加密文件的密码 [student@workstation data-variables]$ ansible-vault rekey test.
直线参数方程
如果是在二维坐标系下,已知两个点p1(x1, y1), p2(x2, y2), 很容易求得两点之间的斜率,然后使用y = kx + b计算出k,b值得到直线方程。同理在三维空间下仍然可以使用直线参数方程。
x = x1 + dx * t,
y = y1 + dy * t,
z = z1 + dz * t
例如:
已知p1(x1, y1, z1), p2(x2, y2, z2)个点,可以求得p1p2两个点的方向向量d。
d = p2 - p1 = ((x2 - x1), (y2 - y1), (z2 - z1))。
可以求得t = |d| / √d。
c++代码求解方程
a.首先定义点的结构
struct Points3D { float x; float y; float z; }; b .
360安全卫士隐藏广告日常去除小技巧,直接重点:
打开“C:\Users\SOLDIER(更改你的用户名)\AppData\Roaming\360safe\SoftMgr”
下面文件都删除(退出360主程序):
360DayPop.exe
360newsld.exe
MultiTip.exe
webapp.exe
然后新建个文本文档,按这几个文件名称(包含后缀),重新命名。
然后把属性设置为“只读”。
其他路径:C:\Windows\SysWOW64\config\systemprofile\AppData\Roaming\360Safe\SoftMgr
文章来源:360安全卫士隐藏广告日常去除小技巧-91APPS_就要应用网
前言 今天闲来无事,就想着装一下最新版的win11玩一下,然后来来去去还是折腾了一些时间,有遇到一些错误不过最好都找到了解决办法,下面我就分享一下VMware虚拟机安装win11的详细步骤。
VMware安装 这个就没什么说的啦,你电脑上得有个VMware叭,VMware怎么装自己去百度摸索嗷,记得最好是15以上的版本,否则可能有错误安装不了。
安装win11 首先我们要去下载一个win的iso镜像文件,我用的方法是在一个msdn的网站上找到的,百度搜索msdn:
点击红圈勾中的链接,然后跳转到:
网站版本有更新,所以点击那个红圈中的链接:
没有账号的话就选择红圈勾中的第三方登录:
选择win11,跳转到如下界面选择红圈勾中的版本,复制那两个链接进入迅雷或者其他的下载工具,等待下载完成之后,打开VMware,点击创建新的虚拟机,选择典型:
然后选择安装程序光盘映像文件,找到我们刚刚下载的iso文件放进去:
像下面一样选:
给这个虚拟机起个名字:
然后和下面一样默认就好:
然后点击自定义硬件:
这里我们改两个地方,一个是内存拉到8G或者4G(你电脑内存大就可以拉高点):
还有一个是处理器得跟上win11的最低要求,如下:
然后点击关闭完成就可以了。
然后我们去修改虚拟机的设置,首先是选项中的访问控制这一块,我们要加密,密码可以自己随便设置:
然后是高级选项那里勾上UEFI和启用安全引导:
然后还有硬件下面选择添加,添加一个可信平台模块就行:
然后点击完成确定。
开启虚拟机,记住在虚拟机到了下面这个部分时,要快速敲回车渡过去:
然后直接下一页:
点击现在安装,到下面页面时选择我没有产品秘钥:
然后选择专业版:
然后下一页,之前我们这里会报错误“这台电脑无法安装windows11”,但现在就不会出现这个问题了,下面就无脑安装就行。
下面这里选择仅安装就行:
继续点击下一页,后面的操作就是正常操作就可以了,我就不再赘述啦。
前言 在之前看《一个64位操作系统的设计与实现》时,书籍引导扇区的文件系统是FAT12,即使在高级部分(使用物理机启动而不是虚拟机启动)也是使用小型U盘(好像是没超过16MB大小),而现在买不到这么小的U盘,最后我在某宝买了一个30MB大小的,但仍然无法正常编写引导扇区(我记得当时U盘太大会导致无法将U盘格式化为FAT12),对于如何编写基于FAT32文件系统的引导扇区在网上搜寻一圈未发现比较完整细致的讲解和代码(详细看boot.asm,本篇不贴代码),所以本篇Blog自己实现了一段可以运行的引导扇区(U盘方式启动)。
注意:本篇不是一篇教学型Blog,需要一定基础!
准备环境 VMwareDiskGeniusWindows平台+Vscode 参考链接 FAT32文件系统结构
文件结构
正文 零、关于FAT12与FAT32的一点补充 在首次从FAT12更新到FAT32时,面临两个问题:
当rootEntCnt(根目录可容纳的目录项数)在FAT32文件系统为0时,如何判断根目录下文件的数量?或者说什么时候停止搜寻loader/kernel程序?获取表项的算法有变化;(更新:加上挂载时出现的表项异常) 一、使用DiskGenius 准备好一个空U盘,使用DiskGenius将其格式化为FAT32文件系统,簇大小设置为512字节,如下:
然后使用DiskGenius查看一些相关信息并记录,关于FAT32文件系统结构使用其他Blog参考即可(在上面的参考链接中)。
这个界面主要是查看FAT1扇区号、根目录扇区号等等:
这个界面主要是查看文件系统结构数据:
二、从扇区数据从提取信息 在扇区编辑的图中,可以看到关于FAT32文件系统结构的数据,将之提取出,有(详细见boot.asm文件):
其中,oemName、bootSig,volumeID、volumeName、fileSysType是自己定的;
(注意!! 这里的命名有点不那么规范,应当有前缀BS_/BPB_,自己写随意点)
三、Boot程序的自述 当上电自检后,BIOS会将引导扇区(第一个扇区若是以55AA结尾)加载到内存0X7C00处并且执行,boot程序主要是查询是否存在loader.bin程序,若存在则将loader程序加载到内存位置1MB处,在当中涉及FAT32文件系统的组织,查询根目录,在根目录处查找loader程序的簇号,并根据FAT表和loader程序的簇号将loader程序的实体加载到内存中。
四、编写 我是在Windows平台下使用Vscode编写,在Ubuntu下使用nasm指令转为bin文件,然后烧写至U盘中;通过VMware虚拟机(添加U盘启动)运行,运行截图如下,‘C’字符是在loader程序输出:
为什么要跨平台?使用VMware虚拟机调试系统很麻烦,后面考虑使用bximage+bochs调试;
使用bochs 原本打算使用bximage生成一个硬盘镜像,但无奈发现存在一些问题(包括挂载、镜像结构),使之不能运行;解决办法是使用winHex将U盘(尽量选个小一点的U盘,我7.6G用了4个多小时)转成img格式(先保证此img可以在VMware运行,然后再转换),然后在bochs配置文件中更改镜像位置,运行即可。
后记 鉴于代码与注解比较多(350行,大部分是注解),所以将代码文件上传到CSDN,下载即可;免积分!!
文件地址
写引导扇区并不难,主要是理解FAT32文件系统结构,然后编写一些逻辑就好了,所以在这里并不多讲,主要是代码!
更新 原有的boot程序在获取表项时出现点问题;当使用Ubuntu将文件拷贝到挂载点时,竟然不是覆盖!!! 每挂载一次,文件在FAT表项中的位置会往后移动一次(偏移量是所有文件大小所占FAT表项数)。那么此时就出现了一个问题,在原有文件中,只需要读取FAT表第一个扇区就好了,但随着表项的往后移动,就要计算出
想要在站点里弄个站点内部通讯的小功能,遇到一个很神奇的问题:
加了注解的@MessageMapping的Controller类的方法如:
@MessageMapping("/send/{id}") @SendTo("/topic/{id}") public MessageEntity sendMesage(@Payload MessageEntity message){ return message; } 但是前端使用 :
stompClient.send('/app/send/you',{},JSON.stringify({sender:'me',type:'E'})); 前端页面发送没异常,后台也没异常,就是请求不到 上述的Controller加了注解的方法上面。
上网搜索一圈是结果,发现有个国外站点的问题和我这个类似
链接:
Spring 4 WebSocket + sockJS:. Getting "No matching method found" in trace and @MessageMapping handler not invoked - Stack Overflow
其中有一个回答有点接近答案:
WebSocketConfig configuration class should be loaded as part of Servlet configuration, not Root configuration.
Make sure WebSocketConfig.class returned from your implementation of AbstractAnnotationConfigDispatcherServletInitializer.getRootConfigClasses()
If you put it in root context, everything will work fine, you can use SimpMessagingTemplate, broker relay, but not @MessageMapping in controllers.
目录 一、简介二、特点三、常见的中间件1、tomcat2、Jetty3、JBoss4、Weblogic5、WebSphere 一、简介 中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源。中间件位于客户机/ 服务器的操作系统之上,管理计算机资源和网络通讯。是连接两个独立应用程序或独立系统的软件。相连接的系统,即使它们具有不同的接口,但通过中间件相互之间仍能交换信息。
执行中间件的一个关键途径是信息传递。通过中间件,应用程序可以工作于多平台或 OS 环境。
中间件是介于操作系统和应用软件之间,为应用软件提供服务功能的软件,有消息中间件,交易中间件,应用服务器等。由于介于两种软件之间,所以,称为中间件。
二、特点 中间件应具有如下的一些特点:
满足大量应用的需要运行于多种硬件和OS平台支持分布计算,提供跨网络、硬件和OS平台的透明性的应用或服务的交互支持标准的协议支持标准的接口 由于标准接口对于可移植性和标准协议对于互操作性的重要性,中间件已成为许多标准化工作的主要部分。对于应用软件开发,中间件远比操作系统和网络服务更为重 要,中间件提供的程序接口定义了一个相对稳定的高层应用环境,不管底层的计算机硬件和系统软件怎样更新换代,只要将中间件升级更新,并保持中间件对外的接 口定义不变,应用软件几乎不需任何修改,从而保护了企业在应用软件开发和维护中的重大投资。
三、常见的中间件 1、tomcat tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。对于一个初学者来说,可以这样认为,当在一台机器上配置好Apache 服务器,可利用它响应HTML[标准通用标记语言]下的一个应用页面的访问请求。实际上Tomcat是Apache 服务器的扩展,但运行时它是独立运行的,所以当你运行tomcat 时,它实际上作为一个与Apache 独立的进程单独运行的。
当配置正确时,Apache 为HTML页面服务,而Tomcat 实际上运行JSP 页面和Servlet。另外,Tomcat和[IIS]等Web服务器一样,具有处理HTML页面的功能,另外它还是一个Servlet和JSP容器,独立的Servlet容器是Tomcat的默认模式。不过,Tomcat处理静态[HTML]的能力不如Apache服务器。
2、Jetty Jetty 是一个开源的servlet容器,它为基于Java的[web容器],例如JSP和servlet提供运行环境。Jetty是使用Java语言编写的,它的API以一组JAR包的形式发布。开发人员可以将Jetty容器实例化成一个对象,可以迅速为一些独立运行(stand-alone)的Java应用提供网络和web连接。Jetty 可以作为嵌入式服务器使用,Jetty的运行速度较快,而且是轻量级的,可以在Java中可以从test case中控制其运行。从而可以使[自动化测试]不再依赖外部环境,顺利实现自动化测试。
和tomcat比较: Jetty更轻量级。这是相对Tomcat而言的。
由于Tomcat除了遵循Java Servlet规范之外,自身还扩展了大量J2EE特性以满足企业级应用的需求,所以Tomcat是较重量级的,而且配置较Jetty亦复杂许多。但对于大量普通互联网应用而言,并不需要用到Tomcat其他高级特性,所以在这种情况下,使用Tomcat是很浪费资源的。这种劣势放在分布式环境下,更是明显。换成Jetty,每个应用服务器省下那几兆内存,对于大的分布式环境则是节省大量资源。而且,Jetty的轻量级也使其在处理高并发细粒度请求的场景下显得更快速高效。Jetty更灵活,体现在其可插拔性和可扩展性,更易于开发者对Jetty本身进行二次开发,定制一个适合自身需求的Web Server。
相比之下,重量级的Tomcat原本便支持过多特性,要对其瘦身的成本远大于丰富Jetty的成本。用自己的理解,即增肥容易减肥难。
然而,当支持大规模企业级应用时,Jetty也许便需要扩展,在这场景下Tomcat便是更优的。总结:Jetty更满足公有云的分布式环境的需求,而Tomcat更符合企业级环境。
3、JBoss JBoss是一个管理EJB的容器和服务器。它是开放源代码的项目,遵循最新的J2EE规范。从JBoss项目开始至今,它已经从一个EJB容器发展成为一个基于的J2EE的一个web 操作系统(operating system for web),它体现了J2EE规范中最新的技术,在J2EE[应用服务器]领域,JBoss是发展最为迅速的应用服务器。由于JBoss遵循商业友好的LGPL授权分发,并且由开源社区开发,这使得JBoss广为流行,
JBoss应用服务器还具有许多优秀的特质。
JBoss需要的内存和硬盘空间比较小。
安装便捷:解压后,只需配置一些环境变量即可。
JBoss支持"热部署",部署BEAN时,只拷贝BEAN的JAR文件到部署路径下即可自动加载;如果有改动,也会自动更新。
Boss与Web服务器在同一个Java虚拟机中运行,Servlet调用EJB不经过网络,从而大大提高运行效率,提升安全性能。
用户可以直接实施J2EE-EAR,而不是以前分别实施EJB-JAR和Web-WAR,非常方便。
Jboss支持[集群]。
4、Weblogic WebLogic是[美国Oracle公司]出品的一个application server,确切的说是一个基于[JAVAEE]架构的[中间件],WebLogic是用于[开发]、集成、部署和管理大型分布式Web应用、[网络应用]和[数据库应用]的Java[应用服务器]。将Java的动态功能和Java Enterprise标准的安全性引入大型网络应用的开发、集成、部署和管理之中。
5、WebSphere WebSphere 是 IBM 的软件平台。它包含了编写、运行和监视全天候的工业强度的随需应变 Web 应用程序和跨平台、跨产品解决方案所需要的整个中间件基础设施,如服务器、服务和工具。WebSphere 提供了可靠、灵活和健壮的软件。WebSphere 是一个模块化的平台,基于业界支持的开放标准。可以通过受信任和持久的接口,将现有资产插入 WebSphere,可以继续扩展环境。WebSphere 可以在许多平台上运行,包括 Intel、Linux 和 z/OS。
在线字符串哈希/散列工具 在线字符串哈希/散列工
本工具可以获取多种散列方式的哈希值,如MD5,SHA1,SHA224,SHA256,SHA384,SHA512,HmacMD5,HmacSHA1等,基于Crypto-js实现,纯客户端计算。
https://tooltt.com/hash/
Dubbo集成Sleuth+zipkin服务链路追踪 版本介绍:前提条件:操作步骤:一:引入sleuth和zipkin依赖二:引入拦截器依赖三:在配置文件中指定拦截器,使上一步依赖生效四:运行zipkin服务五:在项目配置中指定zipkin服务地址六:通过zipkin可视化界面查看调用链路和耗时 参考资料: 版本介绍: Dubbo:2.7.x
sleuth:3.0.4
zipkin:3.0.4
前提条件: 建好两个集成了dubbo的springboot服务:一个生产者服务,一个消费者服务。前端能够调用消费者接口,消费者接口调用生产者服务。
操作步骤: 一:引入sleuth和zipkin依赖 两个服务分别引入sleuth和zipkin的maven依赖
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-sleuth</artifactId> <version>3.0.4</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-sleuth-zipkin</artifactId> <version>3.0.4</version> </dependency> 二:引入拦截器依赖 如果是springcloud项目,并且已经引入OpenFeign,那么引入sleuth和zipkin依赖即可成功。
如果是dubbo项目,需要再额外引入brave-instrumentation-dubbo依赖(这个依赖就是dubbo拦截器,在服务间通过dubbo上下文传递tranceId)
注意:
Dubbo 2.7.x引入的是brave-instrumentation-dubbo
Dubbo 2.6.x引入的是brave-instrumentation-dubbo-rpc
因为Dubbo 2.7.x和brave-instrumentation-dubbo是apache的项目,而dubbo 2.6.x和brave-instrumentation-dubbo-rpc是Alibaba的项目
<dependency> <groupId>io.zipkin.brave</groupId> <artifactId>brave-instrumentation-dubbo</artifactId> <version>5.13.3</version> </dependency> 三:在配置文件中指定拦截器,使上一步依赖生效 引入依赖之后要在配置文件(application.properties或dubbo.properties)中加入以下配置,这个配置是指定dubbo拦截器为上一步引入的拦截器。
dubbo.provider.filter=tracing dubbo.consumer.filter=tracing 然后在多个服务的调用链路中打印日志就可以看到相同的tranceId
四:运行zipkin服务 从zipkin官网下载相关jar包,并且在本地运行即可
可通过运行成功之后输出的地址访问,这里是默认的地址 127.0.0.1:9411/zipkin
五:在项目配置中指定zipkin服务地址 spring: zipkin: base-url: http://127.0.0.1:9411 六:通过zipkin可视化界面查看调用链路和耗时 配置之后重启服务,再进行服务调用时,即可通过zipkin可视化界面查看调用链路
参考资料: sleuth3.0.4官方文档:https://spring.io/projects/spring-cloud-sleuth
sleuth3.0.4对dubbo的支持:https://docs.spring.io/spring-cloud-sleuth/docs/current/reference/html/integrations.html#sleuth-rpc-dubbo-integration
zipkin官方文档:https://zipkin.io/pages/quickstart.html
spring cloud alibaba dubbo 链路跟踪报错问题解决 java.lang.NoSuchMethodError: 'void com.alibaba.dubbo.rpc.pr…:https://www.jianshu.com/p/5cf443081430
dubbo自定义拦截器:https://blog.csdn.net/Mkhaixian2014/article/details/106584195/
题引:随着国产平板的崛起,越来越多的应用开始适配平板。Android系统的开源注定了它产品的多样性,iOS平板只有固定几个尺寸适配较为简单。但Android平板不一样,尺寸随心所欲。很多手机竖屏的应用在平板上有更多的展示方式,适配变得更加艰难!(本文主要写些关于平板适配的心得,以及与设计对线后的感悟!) 细细想想适配的点有哪些:
dp 与 px资源的读取 关于 dp 与 px 的处理 Android尺寸五花八门,计算出来的宽高dp也有很多种
// 计算函数 private fun getAndroidScreenProperty() { val wm = this.getSystemService(WINDOW_SERVICE) as WindowManager val dm = DisplayMetrics() wm.defaultDisplay.getMetrics(dm) val width = dm.widthPixels // 屏幕宽度(像素) val height = dm.heightPixels // 屏幕高度(像素) val density = dm.density // 屏幕密度(0.75 / 1.0 / 1.5) val densityDpi = dm.densityDpi // 屏幕密度dpi(120 / 160 / 240) // 屏幕宽度算法:屏幕宽度(像素)/屏幕密度 val screenWidth = (width / density).toInt() // 屏幕宽度(dp) val screenHeight = (height / density).