SHA 算法描述与实现

    SHA 算法的原理及实现

章节目录

  1. 简介
  2. 算法描述
    2.1 数据准备
    2.1.1 数据填充
    2.1.2 数据分块
    2.1.3 设置初始 Hash 值
    2.2 Hash 计算
    2.2.1 SHA-1
    2.2.2 SHA-256
    2.2.3 SHA-512
  3. 实现

作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!

简介##

SHA 算法(英语:Secure Hash Algorithm,缩写为SHA)是一个密码散列函数家族,是FIPS所认证的安全散列算法。能计算出一个数字消息所对应到的,长度固定的字符串(又称消息摘要)的算法。且若输入的消息不同,它们对应到不同字符串的机率很高。

本文我们将介绍以下 SHA 算法: SHA-1, SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256.

其中 SHA-224 和 SHA-256 使用相同的算法, 区别在于初始 Hash 值不同, 最终结果只使用算法输出的数据中的前224/256 bit.
SHA-384, SHA-512, SHA-512/224, SHA-512/256 使用相同的算法, 区别在于初始 Hash 值不同, 最终结果只使用算法输出的数据中的前384/512/224/256 bit.
而 SHA-2* 和 SHA-384,SHA-5* 算法也非常类似, 区别在于采用的字(Word) 长度不同, SHA-2*使用 32-bit 的字, 而 其他算法使用 64-bit 的字. 算法的迭代次数也不一样.

算法描述##

本文中将介绍的 SHA 算法的计算步骤从大体上可以分为两步: 数据准备Hash 计算.

数据准备###

在数据准备阶段, 我们也像 MD5 那样, 需要先将数据填充到特定长度,同时将原始数据长度填充进去,然后对数据进行分块, 因为我们的算法是基于块进行的. SHA 家族中的具体算法的实现大体相同, 只是填充长度的bit数,分块大小略有不同而已.

在数据准备阶段我们需要进行三个操作: 数据填充, 数据分块, 设置初始 Hash 值.

数据填充####

我们使用 MMM 表示数据数据, 它的长度使用 lll 表示.

对于算法 SHA-1, SHA-224, SHA-256, 数据填充方法如下:
先填充 1 bit 的 ‘1’ 到数据末尾, 然后紧接着填充 k 个 ‘0’, 这里 k 需要时最小的非负数且满足 l+1+k≡448mod512l+1+k\equiv448mod512l+1+k448mod512, 也即是说需要将原始数据长度填充到差64位就是512的整数倍.
上述操作结束后, 将 lll 表示为 64 bit 的bit数组填充到上述步骤所得的数据之后, 此时我们得到一个长度为512整数倍的数据.

举个例子:
假设我们的数据数据为"abc", 它的长度为24(bit). 我们通过计算得到 k 应该是 423(448 - 1 - 24). 此时填充之后的数据应该如下:
01100001⎵a01100010⎵b01100011⎵c100...00⏞42300...011000⎵t=24⏞64\underbrace{01100001}_{a}\quad \underbrace{01100010}_{b}\quad \underbrace{01100011}_{c}\quad 1 \quad \overbrace{00...00}^{423}\quad \overbrace{00...0\underbrace{11000}_{t=24}}^{64}a01100001b01100010c01100011100...0042300...0t=241100064
填充完成之后的长度是512(bit).

对于算法 SHA-384, SHA-512, SHA-512/224, SHA-512/256, 数据填充方法如下:
先填充 1 bit 的 ‘1’ 到数据末尾, 然后紧接着填充 k 个 ‘0’, 这里 k 需要时最小的非负数且满足 l+1+k≡896mod1024l+1+k\equiv896mod1024l+1+k896mod1024, 也即是说需要将原始数据长度填充到差128位就是1024的整数倍.
上述操作结束后, 将 lll 表示为 128 bit 的bit数组填充到上述步骤所得的数据之后, 此时我们得到一个长度为1024整数倍的数据.

以上述的例子为例:
假设我们的数据数据为"abc", 它的长度为24(bit). 我们通过计算得到 k 应该是 871(896 - 1 - 24). 此时填充之后的数据应该如下:
01100001⎵a01100010⎵b01100011⎵c100...00⏞87100...011000⎵t=24⏞128\underbrace{01100001}_{a}\quad \underbrace{01100010}_{b}\quad \underbrace{01100011}_{c}\quad 1 \quad \overbrace{00...00}^{871}\quad \overbrace{00...0\underbrace{11000}_{t=24}}^{128}a01100001b01100010c01100011100...0087100...0t=2411000128
填充完成之后的长度是1024(bit).

数据分块####

填充后的数据需要被分块.

对于算法 SHA-1, SHA-224, SHA-256,
我们将数据分为 NNN 个 521-bit 的块, 分别表示为
M(1),M(2),...,M(N)M^{(1)}, M^{(2)}, ..., M^{(N)}M(1),M(2),...,M(N)
512-bit 的块又可以被划分为 16 个字(32-bit Word), 分别表示为
M0(i),M1(i),...,M15(i)M^{(i)}_{0}, M^{(i)}_{1}, ..., M^{(i)}_{15}M0(i),M1(i),...,M15(i)

对于算法 SHA-384, SHA-512, SHA-512/224, SHA-512/256
我们将数据分为 NNN 个 1024-bit 的块, 分别表示为
M(1),M(2),...,M(N)M^{(1)}, M^{(2)}, ..., M^{(N)}M(1),M(2),...,M(N)
1024-bit 的块又可以被划分为 16 个字(64-bit Word), 分别表示为
M0(i),M1(i),...,M15(i)M^{(i)}_{0}, M^{(i)}_{1}, ..., M^{(i)}_{15}M0(i),M1(i),...,M15(i)

设置初始 Hash 值####

每个特定的 SHA 算法, 都有相应的初始 Hash 值. 在计算 Hash 之前, 我们需要先将初始值准备好.

为了减少文章篇幅, 这里我们不列出这些初始值和 Hash 计算过程中使用到的常量KKK,后边算法实现中会给出相应数据.

Hash 计算###

SHA-1####

SHA-1 算法要求输入数据的长度不能大于 2642^64264, 最小长度为0.

伪代码如下:

ROTLn(x)=(x&lt;&lt;n)∪(x&gt;&gt;w−n)ROTL^n(x)=(x &lt;&lt; n) \cup (x &gt;&gt; w - n)ROTLn(x)=(x<<n)(x>>wn)

ft(x,y,z)f_t(x,y,z)ft(x,y,z) = {Ch(x,y,z)=(x∩y)⨁(¬x∩z),0≤t≤19Parity(x,y,z)=x⨁y⨁z,20≤t≤39Maj(x,y,z)=(x∩y)⨁(x∩z)⨁(y∩z),40≤t≤59Parity(x,y,z)=x⨁y⨁z,60≤t≤79\begin{cases} Ch(x,y,z)=(x\cap y)\bigoplus (¬x\cap z), \qquad 0\leq t\leq19\\ \quad \\ Parity(x,y,z)=x\bigoplus y\bigoplus z, \qquad 20\leq t\leq39\\ \quad \\ Maj(x,y,z)=(x\cap y)\bigoplus (x\cap z)\bigoplus (y\cap z), \qquad 40\leq t\leq59\\ \quad \\ Parity(x,y,z)=x\bigoplus y\bigoplus z, \qquad 60\leq t\leq79\\ \quad \\ \end{cases}Ch(x,y,z)=(xy)(¬xz),0t19Parity(x,y,z)=xyz,20t39Maj(x,y,z)=(xy)(xz)(yz),40t59Parity(x,y,z)=xyz,60t79

For i=1 to N:
{
    //1. 计算 WtW_tWt
Wt\quad W_tWt = {Mt(0),0≤t≤15ROTL1(Wt−3⨁Wt−8⨁Wt−14⨁Wt−16),16≤t≤79\begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ ROTL^1(W_{t-3}\bigoplus W_{t-8}\bigoplus W_{t-14}\bigoplus W_{t-16}), \qquad 16\leq t\leq79\\ \end{cases}Mt(0),0t15ROTL1(Wt3Wt8Wt14Wt16),16t79

    //2. 初始化工作变量 a, b, c, d, e. 他们用来存储在第 i-1 次迭代式的 Hash 值
    // 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a=H0i−1b=H1i−1c=H2i−1d=H3i−1e=H4i−1\quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ a=H0i1b=H1i1c=H2i1d=H3i1e=H4i1

    // 3
    For t=0 to 79:
    {
T=ROTL5(a)+ft(b,c,d)+e+Kt+Wte=dd=cc=ROTL30(b)b=aa=T\qquad T=ROTL^5(a)+f_t(b,c,d)+e+K_t+W_t \\ \qquad e=d \\ \qquad d=c \\ \qquad c=ROTL^30(b) \\ \qquad b=a \\ \qquad a=T \\ T=ROTL5(a)+ft(b,c,d)+e+Kt+Wte=dd=cc=ROTL30(b)b=aa=T
    }

    //4. 计算第 ithi^{th}ith 中间 hash 值HiH^iHi
H0(i)=a+H0(i−1)H1(i)=b+H1(i−1)H2(i)=c+H2(i−1)H3(i)=d+H3(i−1)H4(i)=e+H4(i−1)\quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ H0(i)=a+H0(i1)H1(i)=b+H1(i1)H2(i)=c+H2(i1)H3(i)=d+H3(i1)H4(i)=e+H4(i1)
}

在经过 N 次迭代之后, 最终结果为 H0(N),H1(N),H2(N),H3(N),H4(N)H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4H0(N),H1(N),H2(N),H3(N),H4(N) 的字节表示依次连接所组成的字节数组.

SHA-256####

SHA-256 算法要求输入数据的长度不能大于 2642^64264, 最小长度为0.

SHA-224 算法的计算过程与 SHA-256 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-224 算法的最终结果是取 SHA-256 算法结果的前 224 bit.

伪代码如下:

SHRn(x)=x&gt;&gt;nSHR^n(x)=x &gt;&gt; nSHRn(x)=x>>n
ROTRn(x)=(x&gt;&gt;n)∪(x&lt;&lt;w−n)ROTR^n(x)=(x &gt;&gt; n)\cup (x &lt;&lt; w - n)ROTRn(x)=(x>>n)(x<<wn)
Σ0{256}(x)=ROTR2(x)⨁ROTR13(x)⨁ROTR22(x)\Sigma^{\{256\}}_0(x)=ROTR^2(x)\bigoplus ROTR^{13}(x)\bigoplus ROTR^{22}(x)Σ0{256}(x)=ROTR2(x)ROTR13(x)ROTR22(x)
Σ1{256}(x)=ROTR6(x)⨁ROTR11(x)⨁ROTR25(x)\Sigma^{\{256\}}_1(x)=ROTR^6(x)\bigoplus ROTR^{11}(x)\bigoplus ROTR^{25}(x)Σ1{256}(x)=ROTR6(x)ROTR11(x)ROTR25(x)
σ0{256}(x)=ROTR7(x)⨁ROTR18(x)⨁SHR3(x)\sigma^{\{256\}}_0(x)=ROTR^7(x)\bigoplus ROTR^{18}(x)\bigoplus SHR^3(x)σ0{256}(x)=ROTR7(x)ROTR18(x)SHR3(x)
σ1{256}(x)=ROTR17(x)⨁ROTR19(x)⨁SHR10(x)\sigma^{\{256\}}_1(x)=ROTR^{17}(x)\bigoplus ROTR^{19}(x)\bigoplus SHR^{10}(x)σ1{256}(x)=ROTR17(x)ROTR19(x)SHR10(x)

For i=1 to N:
{
    //1. 计算 WtW_tWt
Wt\quad W_tWt = {Mt(0),0≤t≤15σ1{256}(Wt−2)+Wt−7+σ0{256}(Wt−15)+Wt−16,16≤t≤63\begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ \sigma^{\{256\}}_1(W_{t-2})+W_{t-7}+\sigma^{\{256\}}_0(W_{t-15})+W_{t-16}, \qquad 16\leq t\leq63\\ \end{cases}Mt(0),0t15σ1{256}(Wt2)+Wt7+σ0{256}(Wt15)+Wt16,16t63

    //2. 初始化工作变量 a, b, c, d, e, f, g, h. 他们用来存储在第 i-1 次迭代式的 Hash 值
    // 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a=H0i−1b=H1i−1c=H2i−1d=H3i−1e=H4i−1f=H5i−1g=H6i−1h=H7i−1\quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ \quad f=H^{i-1}_5 \\ \quad g=H^{i-1}_6 \\ \quad h=H^{i-1}_7 \\ a=H0i1b=H1i1c=H2i1d=H3i1e=H4i1f=H5i1g=H6i1h=H7i1

    // 3
    For t=0 to 63:
    {
T1=h+Σ1{256}(e)+Ch(e,f,g)+K{256}t+WtT2=Σ0{256}(a)+Maj(a,b,c)h=gg=ff=ee=d+T1d=cc=bb=aa=T1+T2\qquad T_1=h+\Sigma^{\{256\}}_1(e)+Ch(e,f,g)+K^{\{256\}_t}+W_t \\ \qquad T_2=\Sigma^{\{256\}}_0(a)+Maj(a,b,c) \\ \qquad h=g \\ \qquad g=f \\ \qquad f=e \\ \qquad e=d+T_1 \\ \qquad d=c \\ \qquad c=b \\ \qquad b=a \\ \qquad a=T_1+T_2 \\ T1=h+Σ1{256}(e)+Ch(e,f,g)+K{256}t+WtT2=Σ0{256}(a)+Maj(a,b,c)h=gg=ff=ee=d+T1d=cc=bb=aa=T1+T2
    }

    //4. 计算第 ithi^{th}ith 中间 hash 值HiH^iHi
H0(i)=a+H0(i−1)H1(i)=b+H1(i−1)H2(i)=c+H2(i−1)H3(i)=d+H3(i−1)H4(i)=e+H4(i−1)H5(i)=b+H5(i−1)H6(i)=c+H6(i−1)H7(i)=d+H7(i−1)\quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ \quad H^{(i)}_5=b+H^{(i-1)}_5 \\ \quad H^{(i)}_6=c+H^{(i-1)}_6 \\ \quad H^{(i)}_7=d+H^{(i-1)}_7 \\ H0(i)=a+H0(i1)H1(i)=b+H1(i1)H2(i)=c+H2(i1)H3(i)=d+H3(i1)H4(i)=e+H4(i1)H5(i)=b+H5(i1)H6(i)=c+H6(i1)H7(i)=d+H7(i1)
}

在经过 N 次迭代之后, 最终结果为 H0(N),H1(N),H2(N),H3(N),H4(N),H5(N),H6(N),H7(N)H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4, H^{(N)}_5, H^{(N)}_6, H^{(N)}_7H0(N),H1(N),H2(N),H3(N),H4(N),H5(N),H6(N),H7(N) 的字节表示依次连接所组成的字节数组.

SHA-512####

SHA-512 算法要求输入数据的长度不能大于 21282^1282128, 最小长度为0.

SHA-384 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-384 算法的最终结果是取 SHA-512 算法结果的前 384 bit.

SHA-512/224 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-512/224 算法的最终结果是取 SHA-512 算法结果的前 224 bit.

SHA-512/256 算法的计算过程与 SHA-512 相同, 却别在于使用的初始化 Hash 值不同, 且 SHA-512/256 算法的最终结果是取 SHA-512 算法结果的前 256 bit.

伪代码如下:

Σ0{512}(x)=ROTR28(x)⨁ROTR34(x)⨁ROTR39(x)\Sigma^{\{512\}}_0(x)=ROTR^{28}(x)\bigoplus ROTR^{34}(x)\bigoplus ROTR^{39}(x)Σ0{512}(x)=ROTR28(x)ROTR34(x)ROTR39(x)
Σ1{512}(x)=ROTR14(x)⨁ROTR18(x)⨁ROTR41(x)\Sigma^{\{512\}}_1(x)=ROTR^{14}(x)\bigoplus ROTR^{18}(x)\bigoplus ROTR^{41}(x)Σ1{512}(x)=ROTR14(x)ROTR18(x)ROTR41(x)
σ0{512}(x)=ROTR1(x)⨁ROTR8(x)⨁SHR7(x)\sigma^{\{512\}}_0(x)=ROTR^1(x)\bigoplus ROTR^8(x)\bigoplus SHR^7(x)σ0{512}(x)=ROTR1(x)ROTR8(x)SHR7(x)
σ1{512}(x)=ROTR19(x)⨁ROTR61(x)⨁SHR6(x)\sigma^{\{512\}}_1(x)=ROTR^{19}(x)\bigoplus ROTR^{61}(x)\bigoplus SHR^6(x)σ1{512}(x)=ROTR19(x)ROTR61(x)SHR6(x)

For i=1 to N:
{
    //1. 计算 WtW_tWt
Wt\quad W_tWt = {Mt(0),0≤t≤15σ1{512}(Wt−2)+Wt−7+σ0{512}(Wt−15)+Wt−16,16≤t≤79\begin{cases} M^{(0)}_t, \qquad 0\leq t\leq15\\ \quad \\ \sigma^{\{512\}}_1(W_{t-2})+W_{t-7}+\sigma^{\{512\}}_0(W_{t-15})+W_{t-16}, \qquad 16\leq t\leq79\\ \end{cases}Mt(0),0t15σ1{512}(Wt2)+Wt7+σ0{512}(Wt15)+Wt16,16t79

    //2. 初始化工作变量 a, b, c, d, e, f, g, h. 他们用来存储在第 i-1 次迭代式的 Hash 值
    // 他们的初始值就是我们在"设置初始 Hash 值"小节中所说的值.
a=H0i−1b=H1i−1c=H2i−1d=H3i−1e=H4i−1f=H5i−1g=H6i−1h=H7i−1\quad a=H^{i-1}_0 \\ \quad b=H^{i-1}_1 \\ \quad c=H^{i-1}_2 \\ \quad d=H^{i-1}_3 \\ \quad e=H^{i-1}_4 \\ \quad f=H^{i-1}_5 \\ \quad g=H^{i-1}_6 \\ \quad h=H^{i-1}_7 \\ a=H0i1b=H1i1c=H2i1d=H3i1e=H4i1f=H5i1g=H6i1h=H7i1

    // 3
    For t=0 to 79:
    {
T1=h+Σ1{512}(e)+Ch(e,f,g)+K{512}t+WtT2=Σ0{512}(a)+Maj(a,b,c)h=gg=ff=ee=d+T1d=cc=bb=aa=T1+T2\qquad T_1=h+\Sigma^{\{512\}}_1(e)+Ch(e,f,g)+K^{\{512\}_t}+W_t \\ \qquad T_2=\Sigma^{\{512\}}_0(a)+Maj(a,b,c) \\ \qquad h=g \\ \qquad g=f \\ \qquad f=e \\ \qquad e=d+T_1 \\ \qquad d=c \\ \qquad c=b \\ \qquad b=a \\ \qquad a=T_1+T_2 \\ T1=h+Σ1{512}(e)+Ch(e,f,g)+K{512}t+WtT2=Σ0{512}(a)+Maj(a,b,c)h=gg=ff=ee=d+T1d=cc=bb=aa=T1+T2
    }

    //4. 计算第 ithi^{th}ith 中间 hash 值HiH^iHi
H0(i)=a+H0(i−1)H1(i)=b+H1(i−1)H2(i)=c+H2(i−1)H3(i)=d+H3(i−1)H4(i)=e+H4(i−1)H5(i)=b+H5(i−1)H6(i)=c+H6(i−1)H7(i)=d+H7(i−1)\quad H^{(i)}_0=a+H^{(i-1)}_0 \\ \quad H^{(i)}_1=b+H^{(i-1)}_1 \\ \quad H^{(i)}_2=c+H^{(i-1)}_2 \\ \quad H^{(i)}_3=d+H^{(i-1)}_3 \\ \quad H^{(i)}_4=e+H^{(i-1)}_4 \\ \quad H^{(i)}_5=b+H^{(i-1)}_5 \\ \quad H^{(i)}_6=c+H^{(i-1)}_6 \\ \quad H^{(i)}_7=d+H^{(i-1)}_7 \\ H0(i)=a+H0(i1)H1(i)=b+H1(i1)H2(i)=c+H2(i1)H3(i)=d+H3(i1)H4(i)=e+H4(i1)H5(i)=b+H5(i1)H6(i)=c+H6(i1)H7(i)=d+H7(i1)
}

在经过 N 次迭代之后, 最终结果为 H0(N),H1(N),H2(N),H3(N),H4(N),H5(N),H6(N),H7(N)H^{(N)}_0, H^{(N)}_1, H^{(N)}_2, H^{(N)}_3, H^{(N)}_4, H^{(N)}_5, H^{(N)}_6, H^{(N)}_7H0(N),H1(N),H2(N),H3(N),H4(N),H5(N),H6(N),H7(N) 的字节表示依次连接所组成的字节数组.

算法实现##

本人使用 go 语言实现了该算法. github:https://github.com/UselezzProgrammer/mycrypto

END!

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

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

相关文章

SHA算法描述及实现

SHA 算法的原理及实现 章节目录 简介算法描述 2.1 数据准备 2.1.1 <数据填充 2.1.2 数据分块 2.1.3 设置初始 Hash 值 2.2 Hash 计算 2.2.1 SHA-1 2.2.2 SHA-256 2.2.3 SHA-512实现<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, …

CNG 关于 Key 相关的操作

章节目录 简介创建 Key查看系统中的 Key从 Windows Store 导出 key导入 Key 到 Windows Store<b>作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢!</b> 简介 CNG 全称 Cryptography API: Next G…

Golang 词法分析器浅析

浅析 Go 语言的词法分析器 章节目录 简介TokenScanner例子 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 简介## 在本文我们将简单的走读 Go 语言的词法分析器实现(go/scanner/scanner.go). 本文基于 G…

如何读懂 C 语言复杂的声明

如何读懂 C 语言复杂的声明 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 参考<<C专家编程>> 废话 虽说 C 语言相比于其他更高级的语言来讲&#xff0c;有着非常精简的语法结构&#xff0c;对…

C 语言笔记: 链表节点实现技巧--struct的妙用

链表节点实现技巧–struct的妙用 作者能力有限, 如果您在阅读过程中发现任何错误, 还请您务必联系本人,指出错误, 避免后来读者再学习错误的知识.谢谢! 废话 C 语言虽然只提供了非常简单的语法&#xff0c;但是丝毫不影响 C 语言程序员使用 C 来实现很多让人叹为观止的高级功能…

协议簇: Media Access Control(MAC) Frame 解析

Media Access Control(MAC) Frame 解析 前言 千里之行&#xff0c;始于足下。 因为个人从事网络协议开发&#xff0c;一直想深入的学习一下协议族&#xff0c;从这篇开始&#xff0c;我将开始记录分享我学习到的网络协议相关的知识 简介 引用百度百科的描述&#xff1a; 数…

协议簇:Ethernet Address Resolution Protocol (ARP) 解析

简介 前面的文章中&#xff0c;我们介绍了 MAC Frame 的帧格式。我们知道&#xff0c;在每个 Ethernet Frame 中都分别包含一个 48 bit 的源物理地址和目的物理地址. 对于源地址很容易理解&#xff0c;该地址可以直接从硬件上读取. 但是对于一个网络节点&#xff0c;他怎么知道…

协议簇:IPv4 解析

简介 IP 是一种无连接的协议. 操作在使用分组交换的链路层&#xff08;如以太网&#xff09;上。此协议会尽最大努力交付数据包。 尽最大努力意味着&#xff1a; IP 协议不保证数据的可靠传输, 没有流量控制机制, 不保证传输序列(意味着 IP 数据包会在传输过程中乱序), 没有…

协议簇:ICMP 解析

简介 ICMP 是 Internet Control Message Protocol 的简写. 它主要用来调试网络通信环境中存在的问题. 比如&#xff0c;当 IP 数据包总是无法正常的发送到目的地址, 当网关没有足够的 buffer 来转发对应的数据包 等问题. 值得一提的是&#xff0c;它属于网络层&#xff0c;不属…

协议簇:TCP 解析: 基础

简介 本文我们将从 RFC 学习一下 RFC793 中描述的 TCP 协议. 这将区别于通常讲解计算机网络书籍中所描述的 TCP. 但他们必然是相统一的&#xff0c;不会互相冲突. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: 建立连接

简介 接前文 协议簇&#xff1a;TCP 解析: 基础&#xff0c; 我们这篇文章来看看 TCP 连接建立的过程&#xff0c;也就是众所周知的”三次握手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议簇&a…

协议簇:TCP 解析: 连接断开

简介 接前文 协议簇&#xff1a;TCP 解析: 建立连接&#xff0c; 我们这篇文章来看看 TCP 连接断开的过程&#xff0c;也就是众所周知的”四次挥手“的具体流程. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&#xff1a;建立连接 协议…

协议簇:TCP 解析: Sequence Number

简介 序列号&#xff08;Sequence Number&#xff09; 是 TCP 协议中非常重要的一个概念&#xff0c;以至于不得不专门来学习一下。这篇文章我们就来解开他的面纱. 在 TCP 的设计中&#xff0c;通过TCP协议发送的每个字节都对应于一个序列号. 由于每个字节都有自己的序列号&a…

协议簇:TCP 解析:TCP 数据传输

简介 前面&#xff0c;我们分别介绍了 TCP 基础知识以及连接的建立和关闭&#xff0c;以及最重要的 Sequence Number 的概念. 本篇文章&#xff0c;我们来介绍一下 TCP 如何传输数据. 系列文章 协议簇&#xff1a;TCP 解析&#xff1a;基础 协议簇&#xff1a;TCP 解析&…

CodeTank iOS App Technical Support

CodeTank iOS App Technical Support For All Email: z253951598outlook.com TEL: 86-17782749061 App Screen Shoots

CentOS 7 防火墙命令

查看防火墙状态 systemctl status firewalld如果已经开启&#xff0c;状态为 active 如果未开启&#xff0c;状态为 inactive 开启防火墙 systemctl start firewalld关闭防火墙 systemctl stop firewalld查看当前防火墙的配置 firewall-cmd --list-all这里&#xff0c;我…

Go Concurrency Patterns: Context

Go Concurrency Patterns: Context 原文地址&#xff1a;https://blog.golang.org/context Introduction 在 Go 语言实现的服务器上&#xff0c;我们总是使用 goroutine 来处理与客户端建立的连接&#xff0c; 给每个连接分配一个独立的 goroutine. 在请求的 handler 中也通常…

Go Concurrency Patterns: Timing out, moving on

原文地址&#xff1a;https://blog.golang.org/concurrency-timeouts 并发变成有它自己的风格. 一个非常好的例子就是 timeout. 虽然 go 的 channel 没有直接支持 timeout 机制&#xff0c;但是要实现它非常容易. 比如说&#xff0c;我们想从一个 channel ch 中接收数据&#…

Go Concurrency Patterns: Pipelines and cancellation

原文地址&#xff1a; https://blog.golang.org/pipelines 简介 Go 语言提供的并发原语使得可以很方便的构建数据流 pipeline&#xff0c;使用这样的 pipeline 可以高效的利用 I/O 和多 cpu 的优势. 这篇文章我们将展示如何构建并使用 pipeline. 什么是 pipeline ? 在 go 语…

QTcpSocket connectToHost 建立连接速度慢问题

问题场景 在使用 QT 开发一个客户端 App 的时候&#xff0c;我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题&#xff1a; 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候&#xff0c;发现连接速度非常慢&#xff08;肉眼可见的慢&#x…