VBWebsocket Help File
Introduction
VBWebsocket is a client side websocket implemented as a VB6 UserControl, and
is the first open VB6 client websocket UserControl implementation to
support both standard and secure connections using SSL/TLS. The API loosely
follows the Java implementation and code flow. It currently supports websocket
protocol 13 as specified in the rfc6455
of the websocket standard. Some accomodations were made for servers that use
none-standard behavior but are mostly industry wide accepted practices. It is
presented as Open Source for a starting point to implement your own as needed
or can be easily used as is. Each VBWebsocket instance represents 1 connection
to a websocket server. Multiple connections can be made by using control arrays
or citing several VBWebsocket controls on your form as needed. Or if you're
feeling motivated the source code could be altered to support multiple connections.
Best practices would suggest that you use the code in your project without compiling
to ocx to avoid collisions with other possibly compiled VBWebsocket ocx controls
by someone else. If you choose to compile to ocx you should rename it to something
else besides VBWebsocket.ocx. Also keeping the ocx in your app folder will help
avoid collisions. The files you will need to include in your project are the
exact same ones included in the project example.
This help file is in a state of flux and will probably change in the future
with additions and edits.
Credits
VBWebsocket uses technology developed by Vladimir Vissoultchev aka wqweto (wqweto@gmail.com)
from his VBAsyncSocket
project for a SSL/TLS socket implementation. Some code contributions were translated
from a chinese blog site by a user named Youran (ur1986@foxmail.com) at https://www.cnblogs.com/xiii/p/7135233.html.
This project would not have been possible without thier contributions. As noted
previously, the rfc standard rfc6455 was followed. Some code from DI
Systems website was followed for UTF8 encoding in VB6. Most of the code
in mWebsocket.bas and Websocket.ctl was created or heavily modified by the author
(me). Also a vbForums
user named Maatooh created the first VB6 class based secure websocket, see the
link below for his project.
If you find any bugs, errors, or have suggestions or comments please feel free
to email me at dethbomb@hotmail.com or visit the vbforums
post.
Links
VBForums VBWebsocket Post:
https://www.vbforums.com/showthread.php?892835-VB6-Visual-Basic-6-Client-Websocket-Control
Websocket Protocol Standard
https://www.rfc-editor.org/rfc/rfc6455.txt
Deflate Compression Standard
https://www.rfc-editor.org/rfc/rfc7692.txt
wqweto VBAsyncSocket Project
https://github.com/wqweto/VbAsyncSocket
IANA Websocket Registry
https://www.iana.org/assignments/websocket/websocket.xml
Maatooh VB6 WSS Websocket project
https://github.com/Maatooh/TlsSocketWSS-vb6
Index
Public
Sub Connect(ByVal Uri As
String, Optional ByVal Port As String, Optional ByVal SubProtocols As String,
Optional ByVal ProtocolExtensions As String, Optional Headers As Collection)The Connect method is used to initiate a connection to a websocket server.
example:
ws.Connect("wss://echo.websocket.org")
| Arguments |
Required |
Type |
Description |
Uri |
required |
String |
The URI (aka URL) of the websocket
server. This should be in the form of: ws[s]://serveraddress.com[:port][/path][?param=value] (items in brackets are optional) if the server is a SSL connection you should use wss:// and port 443, if its a non-secure connection you should use ws:// and port 80 (or the port required by the server) |
[Port] |
optional |
String |
if the port isnt specified in the url then you can pass a port with this parameter. If no ports are specified VBWebsocket uses port 80 for ws:// urls and port 443 for wss:// urls. A port specified in the URL overrides all other ports specified. |
[SubProtocols] |
optional |
String |
Use this parameter to specify the desired high level protocol(s) you want to use. Use a string in a CSV (comma separated values) format aka "MQTT, WAMP, JSON". After connection check the Protocols property to see which protocols the server accepted. |
[ProtocolExtensions] |
optional |
String |
Use this parameter to specify the desired Protocol extension(s) you want to use. Use a string in a CSV (comma separated values) format aka "permessage-deflate, bbf-usp-protocol". Note: the compression extension is handled internally by the websocket. Use the UseCompression property before connecting to enable. Check the IANA websocket registry page for official extensions. |
[Headers] |
optional |
Collection |
This is a collection of additional optional header lines such as "Content-Type: application/json". Specify only the header line, VBWebsocket takes care of any formatting such as adding line feeds. See the piesocket example in the sample code for an example useage. |
Use this method to disconnect from
a websocket server. example: ws.Disconnect
Public Function
GetStatusCodeText(ByVal
statCode As WebsocketStatus) As String Use this to get a friendly error message from a status code or error
number.
Most times this will be the same as reason
parameter in the onError event (unless it is a winsock
error).
| Arguments |
Required |
Type |
Description |
statcode |
required |
This can be a value from the WebSocketStatus enum or a Long error value. |
Public Sub
Send(ByVal Data As Variant,
Optional ByVal NoUTF8Conversion As Boolean)
Use this method to send data to a websocket server. ex: ws.Send("Hello
World!") By default VBWebsocket now sends everything as Text. If you need to send
as Binary, use a Byte Array. If you use a byte array VBWebsocket will automatically
send the Data as untouched binary data. If you send a String, VBWebsocket will
send as Text encoded in UTF8. Use byte arrays for files, pictures, media objects
etc. NEW: you can now send binary strings by setting the extra parameter NoUTF8Conversion
to true. This allows you to use strings to load binary files instead of byte
arrays. under the hood the websocket will convert your string to a byte array
(as-is not with strconv) and send as binary.
| Arguments |
Required |
Type |
Description |
Data |
required |
Variant |
On most websocket servers this will be a string formatted as JSON, XML or plain text. The server you are connecting to, and the application layer protocol you agreed to, determines what and how the data is formatted before you send it. NOTE: This parameter has been changed from String to Variant to allow for sending Byte Arrays as a Binary websocket message. Use strings when sending formatted data such as JSON, XML or plain text, Use Byte Arrays when sending files, picture data, or media objects etc. By default VBWebsocket now sends all data as Text encoded in UTF8. |
NoUTF8Conversion |
Optional |
Boolean |
you can set this optional parameter to True if you want to send a string as binary without UTF8 encoding. Use this for sending Binary strings only such as those loaded from a file, this parameter has no effect on byte arrays. If you set this parameter to true and data is not a string an error will occur. |
Public Sub
SendAdvanced(ByVal
Data As Variant, ByVal OpCode As Long, ByVal blnUTF8Encode As Boolean, Optional
ByVal blnCompressData As Boolean, Optional ByVal blnSetFinBit As Boolean = True,
Optional ByVal RSV1 As Boolean, Optional ByVal RSV2 As Boolean, Optional ByVal
RSV3 As Boolean)
This procedure was added to allow for sending extension data. It gives you fine
grained control over how the websocket message is constructed. Some of the same
rules apply as the regular Send() function,for example: if you specify blnUTF8Encode
then the data should be a text string (or a byte array directly assigned from
a string) or else it will be treated as a binary string. Also if you specify
compression you must have set the UseCompression option to true before connecting.
If you specify compression then RSV1 will be set to true by the websocket. Also
Data can only be a byte array or a string. Empty data can be sent.
| Arguments |
Required |
Type |
Description |
Data |
required |
Variant |
Byte Array or String data. |
OpCode |
required |
Long |
Specify the opCode. You can use the built in opCodes or an extension opCode 3-7, 11-15. any other opcode will cause an error. |
blnUTF8Encode |
optional |
Boolean |
Set to True if you wish to have the websocket encode the data in UTF8 for a String (or Textual) data. The websocket expects a String or Byte Array to be a Native VB6 String encoded in UTF16. If you specify any other type of data with this flag, the data will be corrupted. |
blnCompressData |
optional |
Boolean |
Set to True if you wish the websocket to compress the data before sending. You must have set UseCompression to true before connecting and the server must have accepted the compression extension in order to use compression. If you use this compression flag, the websocket will automatically set RSV1 to true. You can optionally compress the data yourself and set RSV1 to true if you wish. |
blnSetFinBit |
optional |
Boolean |
Set this to False if you dont want the FIN bit set. This is by default True. Normally you only set this to false on opContinue frames. |
RSV1 |
optional |
Boolean |
This is normally reserved for compressed frames or messages. Set to true if data is already compressed. Do not set this if you specify the blnCompressData flag as the websocket will set this automatically. |
RSV2 |
optional |
Boolean |
reserved for use by extensions |
RSV3 |
optional |
Boolean |
reserved for use by extensions |
Public Sub Ping(Optional ByVal
ExtraMsg As String)
Ping the server, an option message can be included such as "Hello".
If the server answers the onPong event will be raised.
Event onMessage(ByVal
Msg As Variant)This event happens when the server sends data to the websocket.
| Parameters |
Type |
Description |
Msg |
Variant |
On most websocket servers this will be a string formatted in JSON, XML or plain text. The server you are connecting to determines what and how the data is formatted before you recieve it. NOTE: this option has been changed from String to Variant in order to support multiple formats. If the server indicates that the Data is binary, Msg will contain a byte array, otherwise it will contain a string. Check the opCode parameter to see what type of data the message contains. You can also use the built in VarType(Msg) function to determine if Msg contains a byte array or string. See the sample code for an example. |
opCode |
If this parameter is opText - 1 the Msg parameter is a text string , if it is opBinary-2 it is a byte array. if it is 3-7 or 11-15 it is extension data and Msg is formatted in a raw untouched byte array(not decompressed either) |
Event onConnect(ByVal
RemoteHost As String, Byval RemoteIP as String, ByVal RemotePort As String)This event occurrs whenever the websocket makes a successful connection
to a websocket server.
| Parameters |
Type |
Description |
RemoteHost |
String |
The resolved remote host name of the websocket server you are connected to. |
RemoteIP |
String |
The IP address of the remote host. |
RemotePort |
String |
The remote port of the websocket server you are connected to. |
This event happens whenever the connection is closed to the remote server.
eCode and reason will be the same as the onError
event.
Event onClose(ByVal
eCode As WebsocketStatus, ByVal reason As String)
| Parameters |
Type |
Description |
eCode |
A error code generated by the server. You can use the function GetStatusCodeText(eCode) function to get an error description which is usually the same as reason. See the onError event for more descriptions of error codes and their meanings. | |
reason |
String |
A user friendly error description of the error that occurred. You can also use GetStatusCodeText function with the eCode to get a error description. |
Event onError(ByVal
eCode As WebsocketStatus, ByVal reason As String)
This event happens whenever an error occurs. eCode is the error number
while reason is a friendly description of the error.
000-999 unused by websocket, an error in this
range will most likely be an internal VB error, such as 5-invalid argument
1000-1015 standard websocket errors aka Close Codes
1016 trapped socket errors
1017-1999 unused or OS (Windows) error
2000-2999 Websocket Extension errors
3000-3999 Library or Framework errors
4000-4999 Application Layer errors
5000-10000 unused or OS (Windows) error
> 10,000 untrapped Winsock errors
| Parameters |
Type |
Description |
eCode |
A error code generated by the websocket. This can also be an underlying winsock error. If code is 1016 (WebsocketStatus.WinsockError) then it is an internal socket or winsock error. You can use the function GetStatusCodeText(eCode) function to get an error description which is usually the same as reason. | |
reason |
String |
A user friendly error description of the error that occurred. You can also use GetStatusCodeText function with the eCode to get a error description. |
Event onProgress(ByVal
bytesSent As Long, ByVal bytesMax As Long, Cancel As Boolean)This event occurrs whenever the websocket is making large data sends
greater than 4kb to the server. You can set the byref Cancel parameter to True
to cancel the send.
To get bytesRemaining use (bytesMax - bytesSent).
When bytesSent = bytesMax then the send is complete.
| Parameters |
Type |
Description |
bytesSent |
Long |
The number of bytes that have been sent in the current message |
bytesMax |
Long |
the total number of bytes in the message |
Cancel |
Boolean |
A byref parameter that you can set to True to cancel the send. |
Event onPong(ByVal
IncludedMsg As String)This event happens when the server answers a Ping message from the websocket.
Sometimes the server may include an extra message such as "Pong" or
"Hello".
| Parameters |
Type |
Description |
IncludedMsg |
String |
The server may include an extra message such as "Pong" or "Hello" otherwise this will be an empty string. |
This event happens whenever the connection is redirected by the remote
server in the HTTP Handshake. The parameter newURI will have the redirect url
value. This lets you update the URI in the GUI for the user.
Event
onReConnect(ByVal newURI As String)
| Parameters |
Type |
Description |
newURI |
String |
The new Url that the connection is being directed to. |
The WebsocketStatus
enum is a list of error codes that are websocket specific. These are called
Close codes because the connection is always closed after these errors.
Public Enum WebsocketStatus
NormalClosure = 1000
GoingAway = 1001
ProtocolError = 1002
UnsupportedData = 1003
StatusReserved = 1004
NoStatusReceived = 1005
AbNormalClosure = 1006
InvalidData = 1007
PolicyViolation = 1008
MessageToLarge = 1009
MandatoryExtension = 1010
InternalError = 1011
ServiceRestart = 1012
TryAgainLater = 1013
BadGateWay = 1014
SslTlsHandshake = 1015
End Enum
The
WebsocketState enum
is a list of connection states the websocket is in. Check the readyState
property to get current status.
Public Enum WebSocketState
STATE_CLOSED
STATE_OPEN
STATE_CONNECTING
STATE_CLOSING
End Enum
this enum defines the websocket operation codes aka op codes, op codes 3-7 and
11-15 are extension codes and data must be handled by the application, any other
opcodes are invalid.
Public Enum WebsocketOpCode
opContinue = 0 ' successive message frame
opText = 1 ' text
message frame
opBinary = 2 ' binary message
frame
opClose = 8 ' connection
closing
OpPing = 9 ' ping
heartbeat check
opPong = 10 ' ping heartbeat
answer
End Enum
Property Get
readyState() As WebSocketStateRead the readystate property for
information on the current connection state of the websocket. See the WebsocketState
enum for a list of possible values.
(Read-Only) Property
Get Protocols()
As String
Read this property to see what protocols
the server has accepted from the SubProtocols you specified in the Connect
method.
(Read-Only) Property
Get Extensions()
As String
Read this property to see what Extensions the server has accepted from the ProtocolExtensions you specified in the Connect method.
(Read-Write)
Property Let/Get UseCompression()
As Boolean
Set this property to send and recieve
compressed data. Note that this is handled internally. You should not try to
compress/decompress the data yourself (if you use this property), as it will
result in data corruption.
(Read-Only)
Property Get isBusy()
As Boolean
If this property returns True, the
websocket is in the middle of sending or receiving data.
(Read-Write)
Property Let/Get ChunkSize()
As Double
Set or read this property to get/set
the chunk size of data that the websocket sends to the server. the websocket
protocol specifies 3 sizes for sending a data frame, (1)0-125 bytes, (2)126-65535
bytes and (3)65536-2147483647(2.1 Gb) bytes.
The websocket protocol also allows for splitting up data into smaller chunks
and sending in multiple split packets called continue frames.The chunk size
determines at what size the websocket will split up the data into multiple data
frames to send. For example lets say you are sending 41kb of data in one send
and chunksize is 4kb. The websocket will split up the send into 10 - 4kb sends
and the last packet will be the remaining 1kb. If you frequently send large
packets you can fine tune the data chunk size to be more effecient knowing that
most winsock frames are 16kb in size (4kb on older systems)..
This value should be an evenly divisible number (modulo) of 1024