VB封装的WebSocket模块,拿来即用
一共就下面的两个模块,调用只使用到mWSProtocol模块,所有调用函数功能简单介绍一下:
建立连接后就开始握手,服务端用Handshake()验证,如果是客户端自己发送握手封包
接收数据,先用AnalyzeHeader()得到数据帧结构(DataFrame)
然后再用PickDataV()或PickData()得到源数据进行处理
发送数据需要先进行数据帧包装:
服务端向客户端发送无需掩码,用PackString()或PackData()
而模拟客户端向服务器的发送需要加掩码,用PackMaskString()或PackMaskData()
相关资料下载:《WebSocket协议中文版.pdf》
第二次写了,完全是为了分享...如果对你有帮助就支持一下吧
mWSProtocol:
Option Explicit
Option Compare Text
'==============================================================
'By: 悠悠然
'QQ: 2860898817
'E-mail: ur1986@foxmail.com
'完整运行示例放Q群文件共享:369088586
'==============================================================
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Public Enum OpcodeType
opContin = '连续消息片断
opText = '文本消息片断
opBinary = '二进制消息片断
'3 - 7 非控制帧保留
opClose = '连接关闭
opPing = '心跳检查的ping
opPong = '心跳检查的pong
'11-15 控制帧保留
End Enum
Public Type DataFrame
FIN As Boolean '0表示不是当前消息的最后一帧,后面还有消息,1表示这是当前消息的最后一帧;
RSV1 As Boolean '1位,若没有自定义协议,必须为0,否则必须断开.
RSV2 As Boolean '1位,若没有自定义协议,必须为0,否则必须断开.
RSV3 As Boolean '1位,若没有自定义协议,必须为0,否则必须断开.
Opcode As OpcodeType '4位操作码,定义有效负载数据,如果收到了一个未知的操作码,连接必须断开.
MASK As Boolean '1位,定义传输的数据是否有加掩码,如果有掩码则存放在MaskingKey
MaskingKey() As Byte '32位的掩码
Payloadlen As Long '传输数据的长度
DataOffset As Long '数据源起始位
End Type '==============================================================
'握手部分,只有一个开放调用函数 Handshake(requestHeader As String) As Byte()
'==============================================================
Private Const MagicKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
Private Const B64_CHAR_DICT = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
Public Function Handshake(requestHeader As String) As Byte()
Dim clientKey As String
clientKey = getHeaderValue(requestHeader, "Sec-WebSocket-Key:")
Dim AcceptKey As String
AcceptKey = getAcceptKey(clientKey)
Dim response As String
response = "HTTP/1.1 101 Web Socket Protocol Handshake" & vbCrLf
response = response & "Upgrade: WebSocket" & vbCrLf
response = response & "Connection: Upgrade" & vbCrLf
response = response & "Sec-WebSocket-Accept: " & AcceptKey & vbCrLf
response = response & "WebSocket-Origin: " & getHeaderValue(requestHeader, "Sec-WebSocket-Origin:") & vbCrLf
response = response & "WebSocket-Location: " & getHeaderValue(requestHeader, "Host:") & vbCrLf
response = response & vbCrLf
'Debug.Print response
Handshake = StrConv(response, vbFromUnicode)
End Function
Private Function getHeaderValue(str As String, pname As String) As String
Dim i As Long, j As Long
i = InStr(str, pname)
If i > Then
j = InStr(i, str, vbCrLf)
If j > Then
i = i + Len(pname)
getHeaderValue = Trim(Mid(str, i, j - i))
End If
End If
End Function
Private Function getAcceptKey(key As String) As String
Dim b() As Byte
b = mSHA1.SHA1(StrConv(key & "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", vbFromUnicode))
getAcceptKey = EnBase64(b)
End Function
Private Function EnBase64(str() As Byte) As String
On Error GoTo over
Dim buf() As Byte, length As Long, mods As Long
mods = (UBound(str) + ) Mod
length = UBound(str) + - mods
ReDim buf(length / * + IIf(mods <> , , ) - )
Dim i As Long
For i = To length - Step
buf(i / * ) = (str(i) And &HFC) / &H4
buf(i / * + ) = (str(i) And &H3) * &H10 + (str(i + ) And &HF0) / &H10
buf(i / * + ) = (str(i + ) And &HF) * &H4 + (str(i + ) And &HC0) / &H40
buf(i / * + ) = str(i + ) And &H3F
Next
If mods = Then
buf(length / * ) = (str(length) And &HFC) / &H4
buf(length / * + ) = (str(length) And &H3) * &H10
buf(length / * + ) =
buf(length / * + ) =
ElseIf mods = Then
buf(length / * ) = (str(length) And &HFC) / &H4
buf(length / * + ) = (str(length) And &H3) * &H10 + (str(length + ) And &HF0) / &H10
buf(length / * + ) = (str(length + ) And &HF) * &H4
buf(length / * + ) =
End If
For i = To UBound(buf)
EnBase64 = EnBase64 + Mid(B64_CHAR_DICT, buf(i) + , )
Next
over:
End Function
'==============================================================
'数据帧解析,返回帧结构
'==============================================================
Public Function AnalyzeHeader(byt() As Byte) As DataFrame
Dim DF As DataFrame
DF.FIN = IIf((byt() And &H80) = &H80, True, False)
DF.RSV1 = IIf((byt() And &H40) = &H40, True, False)
DF.RSV2 = IIf((byt() And &H20) = &H20, True, False)
DF.RSV3 = IIf((byt() And &H10) = &H10, True, False)
DF.Opcode = byt() And &H7F
DF.MASK = IIf((byt() And &H80) = &H80, True, False)
Dim plen As Byte
plen = byt() And &H7F
If plen < Then
DF.Payloadlen = plen
If DF.MASK Then
CopyMemory DF.MaskingKey(), byt(),
DF.DataOffset =
Else
DF.DataOffset =
End If
ElseIf plen = Then
Dim l() As Byte
l() = byt()
l() = byt()
CopyMemory DF.Payloadlen, l(),
If DF.MASK Then
CopyMemory DF.MaskingKey(), byt(),
DF.DataOffset =
Else
DF.DataOffset =
End If
ElseIf plen = Then
'这部分没有什么意义就不写了,因为VB没有64位的整型可供使用
'所以对长度设定为-1,自己再判断
DF.Payloadlen = -
'If df.mask Then
' CopyMemory df.MaskingKey(0), byt(10), 4
' df.DataOffset = 14
'Else
' df.DataOffset = 10
'End If
End If
AnalyzeHeader = DF
End Function
'==============================================================
'接收的数据处理,有掩码就反掩码
'PickDataV 方法是出于性能的考虑,用于有时数据只是为了接收,做一些逻辑判断,并不需要对数据块进行单独提炼
'PickData 不赘述了...
'==============================================================
Public Sub PickDataV(byt() As Byte, dataType As DataFrame)
Dim lenLimit As Long
lenLimit = dataType.DataOffset + dataType.Payloadlen -
If dataType.MASK And lenLimit <= UBound(byt) Then
Dim i As Long, j As Long
For i = dataType.DataOffset To lenLimit
byt(i) = byt(i) Xor dataType.MaskingKey(j)
j = j +
If j = Then j =
Next i
End If
End Sub
Public Function PickData(byt() As Byte, dataType As DataFrame) As Byte()
Dim b() As Byte
PickDataV byt, dataType
ReDim b(dataType.Payloadlen - )
CopyMemory b(), byt(dataType.DataOffset), dataType.Payloadlen
PickData = b
End Function '==============================================================
'发送的数据处理,该部分未联网测试,使用下面的方式测试验证
'Private Sub Command1_Click()
' Dim str As String, b() As Byte, bs() As Byte
' Dim DF As DataFrame
' str = "abc123"
' Showlog "组装前数据:" & str
' b = mWSProtocol.PackMaskString(str): Showlog "掩码后字节:" & BytesToHex(b)
' DF = mWSProtocol.AnalyzeHeader(b): Showlog "结构体偏移:" & DF.DataOffset & " 长度:" & DF.Payloadlen
' bs = mWSProtocol.PickData(b, DF): Showlog "还原后字节:" & BytesToHex(bs)
' Showlog "还原后数据:" & StrConv(bs, vbUnicode)
'End Sub
'==============================================================
'无掩码数据的组装,用于服务端向客户端发送
'--------------------------------------------------------------
Public Function PackString(str As String, Optional dwOpcode As OpcodeType = opText) As Byte()
Dim b() As Byte
b = StrConv(str, vbFromUnicode)
PackString = PackData(b, dwOpcode)
End Function
Public Function PackData(data() As Byte, Optional dwOpcode As OpcodeType = opText) As Byte()
Dim length As Long
Dim byt() As Byte
length = UBound(data) + If length < Then
ReDim byt(length + )
byt() = CByte(length)
CopyMemory byt(), data(), length
ElseIf length <= Then
ReDim byt(length + )
Dim l() As Byte
byt() = &H7E
CopyMemory l(), length,
byt() = l()
byt() = l()
CopyMemory byt(), data(), length
'ElseIf length <= 999999999999999# Then
'这么长不处理了...
'VB6也没有这么大的整型
'有需要就根据上面调整来写吧
End If
'------------------------------
'关于下面的 byt(0) = &H80 Or dwOpcode 中,&H80 对应的是 DataFrame 结构中的FIN + RSV1 + RSV2 + RSV3
'FIN 的中文解释是:指示这个是消息的最后片段,第一个片段可能也是最后的片段。
'这里我不是很理解,可能是自定义分包用到吧,但貌似分包应该不是自己可控的,所以我默认是 1。
'------------------------------
byt() = &H80 Or dwOpcode
PackData = byt
End Function
'--------------------------------------------------------------
'有掩码数据的组装,用于替代客户端想服务端发送
'--------------------------------------------------------------
Public Function PackMaskString(str As String) As Byte()
Dim b() As Byte
b = StrConv(str, vbFromUnicode)
PackMaskString = PackMaskData(b)
End Function
Public Function PackMaskData(data() As Byte) As Byte()
'对源数据做掩码处理
Dim mKey() As Byte
mKey() = : mKey() = : mKey() = : mKey() = '掩码,你也可以自己定义
Dim i As Long, j As Long
For i = To UBound(data)
data(i) = data(i) Xor mKey(j)
j = j +
If j = Then j =
Next i
'包装,和上面的无掩码包装PackData()大体相同
Dim length As Long
Dim byt() As Byte
length = UBound(data) +
If length < Then
ReDim byt(length + )
byt() = &H81 '注意这里是按照OpcodeType里面的文本类型,其他类型,比如字节包应该是 byt(0) = &h80 or OpcodeType.opBinary
byt() = (CByte(length) Or &H80)
CopyMemory byt(), mKey(),
CopyMemory byt(), data(), length
ElseIf length <= Then
ReDim byt(length + )
Dim l() As Byte
byt() = &H81 '同上注意
byt() = &HFE '固定 掩码位+126
CopyMemory l(), length,
byt() = l()
byt() = l()
CopyMemory byt(), mKey(),
CopyMemory byt(), data(), length
'ElseIf length <= 999999999999999# Then
'这么长不处理了...有需要就根据上面调整来写吧
End If
PackMaskData = byt
End Function
'==============================================================
'控制帧相关,Ping、Pong、Close 用于服务端向客户端发送未经掩码的信号
'我用的0长度,其实是可以包含数据的,但是附带数据客户端处理又麻烦了
'
'* 如果有附带信息的需求,也可以用PackString或PackData,可选参数指定OpcodeType
'==============================================================
Public Function PingFrame() As Byte()
Dim b() As Byte
b() = &H89
b() = &H0
PingFrame = b
'发送一个包含"Hello"的Ping信号: 0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f
End Function
Public Function PongFrame() As Byte()
Dim b() As Byte
b() = &H8A
b() = &H0
PongFrame = b
'发送一个包含"Hello"的Pong信号: 0x8A 0x05 0x48 0x65 0x6c 0x6c 0x6f
End Function
Public Function CloseFrame() As Byte()
Dim b() As Byte
b() = &H88
b() = &H0
CloseFrame = b
'发送一个包含"Close"的Pong信号: 0x8A 0x05 0x43 0x6c 0x6f 0x73 0x65
End Function
mSHA1:
Option Explicit
'==============================================================
'该模块来自网络资料,进行了小改动,源作者不详
'==============================================================
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal length As Long)
Private Type Word
B0 As Byte
B1 As Byte
B2 As Byte
B3 As Byte
End Type
Private Function AndW(w1 As Word, w2 As Word) As Word
AndW.B0 = w1.B0 And w2.B0
AndW.B1 = w1.B1 And w2.B1
AndW.B2 = w1.B2 And w2.B2
AndW.B3 = w1.B3 And w2.B3
End Function Private Function OrW(w1 As Word, w2 As Word) As Word
OrW.B0 = w1.B0 Or w2.B0
OrW.B1 = w1.B1 Or w2.B1
OrW.B2 = w1.B2 Or w2.B2
OrW.B3 = w1.B3 Or w2.B3
End Function Private Function XorW(w1 As Word, w2 As Word) As Word
XorW.B0 = w1.B0 Xor w2.B0
XorW.B1 = w1.B1 Xor w2.B1
XorW.B2 = w1.B2 Xor w2.B2
XorW.B3 = w1.B3 Xor w2.B3
End Function Private Function NotW(w As Word) As Word
NotW.B0 = Not w.B0
NotW.B1 = Not w.B1
NotW.B2 = Not w.B2
NotW.B3 = Not w.B3
End Function Private Function AddW(w1 As Word, w2 As Word) As Word
Dim i As Long, w As Word
i = CLng(w1.B3) + w2.B3
w.B3 = i Mod
i = CLng(w1.B2) + w2.B2 + (i \ )
w.B2 = i Mod
i = CLng(w1.B1) + w2.B1 + (i \ )
w.B1 = i Mod
i = CLng(w1.B0) + w2.B0 + (i \ )
w.B0 = i Mod
AddW = w
End Function Private Function CircShiftLeftW(w As Word, n As Long) As Word
Dim d1 As Double, d2 As Double
d1 = WordToDouble(w)
d2 = d1
d1 = d1 * ( ^ n)
d2 = d2 / ( ^ ( - n))
CircShiftLeftW = OrW(DoubleToWord(d1), DoubleToWord(d2))
End Function Private Function WordToHex(w As Word) As String
WordToHex = Right$("" & Hex$(w.B0), ) & Right$("" & Hex$(w.B1), ) & Right$("" & Hex$(w.B2), ) & Right$("" & Hex$(w.B3), )
End Function Private Function HexToWord(H As String) As Word
HexToWord = DoubleToWord(Val("&H" & H & "#"))
End Function Private Function DoubleToWord(n As Double) As Word
DoubleToWord.B0 = Int(DMod(n, ^ ) / ( ^ ))
DoubleToWord.B1 = Int(DMod(n, ^ ) / ( ^ ))
DoubleToWord.B2 = Int(DMod(n, ^ ) / ( ^ ))
DoubleToWord.B3 = Int(DMod(n, ^ ))
End Function Private Function WordToDouble(w As Word) As Double
WordToDouble = (w.B0 * ( ^ )) + (w.B1 * ( ^ )) + (w.B2 * ( ^ )) + w.B3
End Function Private Function DMod(value As Double, divisor As Double) As Double
DMod = value - (Int(value / divisor) * divisor)
If DMod < Then DMod = DMod + divisor
End Function Private Function F(t As Long, b As Word, C As Word, D As Word) As Word
Select Case t
Case Is <=
F = OrW(AndW(b, C), AndW(NotW(b), D))
Case Is <=
F = XorW(XorW(b, C), D)
Case Is <=
F = OrW(OrW(AndW(b, C), AndW(b, D)), AndW(C, D))
Case Else
F = XorW(XorW(b, C), D)
End Select
End Function
Public Function StringSHA1(inMessage As String) As String
' 计算字符串的SHA1摘要
Dim inLen As Long
Dim inLenW As Word
Dim padMessage As String
Dim numBlocks As Long
Dim w( To ) As Word
Dim blockText As String
Dim wordText As String
Dim i As Long, t As Long
Dim temp As Word
Dim k( To ) As Word
Dim H0 As Word
Dim H1 As Word
Dim H2 As Word
Dim H3 As Word
Dim H4 As Word
Dim A As Word
Dim b As Word
Dim C As Word
Dim D As Word
Dim E As Word
inMessage = StrConv(inMessage, vbFromUnicode)
inLen = LenB(inMessage)
inLenW = DoubleToWord(CDbl(inLen) * )
padMessage = inMessage & ChrB() _
& StrConv(String(( - (inLen Mod ) - ) Mod + , Chr()), ) _
& ChrB(inLenW.B0) & ChrB(inLenW.B1) & ChrB(inLenW.B2) & ChrB(inLenW.B3)
numBlocks = LenB(padMessage) /
k() = HexToWord("5A827999")
k() = HexToWord("6ED9EBA1")
k() = HexToWord("8F1BBCDC")
k() = HexToWord("CA62C1D6")
H0 = HexToWord("")
H1 = HexToWord("EFCDAB89")
H2 = HexToWord("98BADCFE")
H3 = HexToWord("")
H4 = HexToWord("C3D2E1F0")
For i = To numBlocks -
blockText = MidB$(padMessage, (i * ) + , )
For t = To
wordText = MidB$(blockText, (t * ) + , )
w(t).B0 = AscB(MidB$(wordText, , ))
w(t).B1 = AscB(MidB$(wordText, , ))
w(t).B2 = AscB(MidB$(wordText, , ))
w(t).B3 = AscB(MidB$(wordText, , ))
Next
For t = To
w(t) = CircShiftLeftW(XorW(XorW(XorW(w(t - ), w(t - )), w(t - )), w(t - )), )
Next
A = H0
b = H1
C = H2
D = H3
E = H4
For t = To
temp = AddW(AddW(AddW(AddW(CircShiftLeftW(A, ), _
F(t, b, C, D)), E), w(t)), k(t \ ))
E = D
D = C
C = CircShiftLeftW(b, )
b = A
A = temp
Next
H0 = AddW(H0, A)
H1 = AddW(H1, b)
H2 = AddW(H2, C)
H3 = AddW(H3, D)
H4 = AddW(H4, E)
Next
StringSHA1 = WordToHex(H0) & WordToHex(H1) & WordToHex(H2) & WordToHex(H3) & WordToHex(H4)
End Function
'计算字节数组的SHA1摘要
Public Function SHA1(inMessage() As Byte) As Byte()
Dim inLen As Long
Dim inLenW As Word
Dim numBlocks As Long
Dim w( To ) As Word
Dim blockText As String
Dim wordText As String
Dim t As Long
Dim temp As Word
Dim k( To ) As Word
Dim H0 As Word
Dim H1 As Word
Dim H2 As Word
Dim H3 As Word
Dim H4 As Word
Dim A As Word
Dim b As Word
Dim C As Word
Dim D As Word
Dim E As Word
Dim i As Long
Dim lngPos As Long
Dim lngPadMessageLen As Long
Dim padMessage() As Byte
inLen = UBound(inMessage) +
inLenW = DoubleToWord(CDbl(inLen) * )
lngPadMessageLen = inLen + + ( - (inLen Mod ) - ) Mod +
ReDim padMessage(lngPadMessageLen - ) As Byte
For i = To inLen -
padMessage(i) = inMessage(i)
Next i
padMessage(inLen) =
padMessage(lngPadMessageLen - ) = inLenW.B0
padMessage(lngPadMessageLen - ) = inLenW.B1
padMessage(lngPadMessageLen - ) = inLenW.B2
padMessage(lngPadMessageLen - ) = inLenW.B3
numBlocks = lngPadMessageLen /
k() = HexToWord("5A827999")
k() = HexToWord("6ED9EBA1")
k() = HexToWord("8F1BBCDC")
k() = HexToWord("CA62C1D6")
H0 = HexToWord("")
H1 = HexToWord("EFCDAB89")
H2 = HexToWord("98BADCFE")
H3 = HexToWord("")
H4 = HexToWord("C3D2E1F0")
For i = To numBlocks -
For t = To
w(t).B0 = padMessage(lngPos)
w(t).B1 = padMessage(lngPos + )
w(t).B2 = padMessage(lngPos + )
w(t).B3 = padMessage(lngPos + )
lngPos = lngPos +
Next
For t = To
w(t) = CircShiftLeftW(XorW(XorW(XorW(w(t - ), w(t - )), w(t - )), w(t - )), )
Next
A = H0
b = H1
C = H2
D = H3
E = H4
For t = To
temp = AddW(AddW(AddW(AddW(CircShiftLeftW(A, ), _
F(t, b, C, D)), E), w(t)), k(t \ ))
E = D
D = C
C = CircShiftLeftW(b, )
b = A
A = temp
Next
H0 = AddW(H0, A)
H1 = AddW(H1, b)
H2 = AddW(H2, C)
H3 = AddW(H3, D)
H4 = AddW(H4, E)
Next
Dim byt() As Byte
CopyMemory byt(), H0,
CopyMemory byt(), H1,
CopyMemory byt(), H2,
CopyMemory byt(), H3,
CopyMemory byt(), H4,
SHA1 = byt
End Function
VB封装的WebSocket模块,拿来即用的更多相关文章
- C#封装的websocket协议类
关于VB版之前已经写了,有需要可以进传送门<VB封装的WebSocket模块,拿来即用>,两个使用都差不多,这里简单概述一下: 连接完成后,没有握手就用Handshake()先完成握手之后 ...
- 【转】利用Boost.Python将C++代码封装为Python模块
用Boost.Python将C++代码封装为Python模块 一. 基础篇 借助Boost.Python库可以将C/C++代码方便.快捷地移植到python模块当中,实现对python模块的扩 ...
- VB.NET中的模块
在C#中有“静态类”的概念,自然里边全部的方法都是静态的.这意味着你可以直接通过"类名.方法名"去调用(例如System的Math类就是典型).在VB.NET中,没有“静态类”的概 ...
- DRF框架之视图方法的几个封装好的模块介绍(第三天)
1.DRF框架给我们封装好了好多层模块的 来实现简便接口的编写 # from rest_framework.mixins import CreateModelMixin, UpdateModelMix ...
- 封装篇——图片模块(Glide)
如今市面上差点儿全部的app都用到了图片,图片模块的开发是app开发中不可缺少的一块工作, 开源的力量是强大的.好多优秀的第三方项目能够任君使用,帮助我们提高效率.而且不须要反复造轮子,这边我採用的是 ...
- 结合manage.py,在flask项目中使用websocket模块--- flask-socketio
前言: - 为什么我要使用 flask-socketio模块,而不是flask-sockets? - 因为flask-socketio与前端流行的websocket库socke ...
- python中协程实现的本质以及两个封装协程模块greenle、gevent
协程 协程,又称微线程,纤程.英文名Coroutine. 协程是啥 协程是python个中另外一种实现多任务的方式,只不过比线程更小占用更小执行单元(理解为需要的资源). 为啥说它是一个执行单元,因为 ...
- python笔记5 接口类抽象类 封装 反射 设计模式 模块 :random随机数 josn shelve持久化存储
接口类抽象类 接口类:接口类就是制定一个规则,让其他人按照我的规则去写程序. #!/usr/bin/env python from abc import ABCMeta,abstractmethod ...
- jquery插件封装成seajs模块
jquery直接在html中引入. jquery插件修改为: define(function (require, exports, moudles) { return function (jquery ...
随机推荐
- shell 通过EOF在脚本中输入需要的用户名或密码
参考地址:https://www.cnblogs.com/liyuanhong/p/10390786.html expect使用参考:https://www.cnblogs.com/liyuanhon ...
- 金融量化分析【day112】:股票数据分析Tushare2
目录 1.使用tushare包获取某股票的历史行情数据 2.使用pandas包计算该股票历史数据的5日局限和60日均线 3.matplotlib包可视化历史数据的收盘价和历史均线 4.分析输出所有金叉 ...
- SpringCloud笔记五:Feign
目录 什么是Feign? 有了Ribbon我还要Feign干嘛? 新建consumer-feign 修改api项目 引入Maven文件 新建feign的接口 启动项目 报错 发泄发泄心情,一个段落 什 ...
- SpringCloud笔记三:Eureka服务注册与发现
目录 什么是Eureka? Eureka注册的三大步 第一步,引用Maven 第二步,配置yml 第三步,开启Eureka注解 新建Eureka子项目 把provider子项目变成服务端 Eureka ...
- 搞数学的牛群[主要PDE的]
- [译]Ocelot - Delegating Handlers
原文 可以为HttpClient添加delegating handlers. Usage 为了添加delegating handler需要做两件事. 首先如下一样创建一个类. public class ...
- win10免安装版本的MySQL的下载安装和配置
下载mysql-xxx.zip(免安装版) 解压到自己想要的目录下(我的是D:\mysql\),打开mysql-5.7.21-winx64文件夹,新建my.ini文件,输入: [mysql] # 设置 ...
- 412 6个题 BOM and DOM 定义计数器 网页跳转 网页前进后退
AM BOM-JavaScript: 提供一系列对象哟用于和浏览器窗口交互,对象主要有 window.document.location.navigator.screen 统称浏览器对象模型(Brow ...
- 【Java编程思想笔记】注解--自定义注解
文章参考自:https://www.cnblogs.com/xdp-gacl/p/3622275.html 学习网站:how2java.cn 一.自定义注解的创建过程 第一步:(元注解) 使用元注 ...
- Django过滤器
在项目目录下建立templatetags文件 夹 建立 my_filter.py文件 from django import template register = template.Library() ...