Websocket technical background
WebSocket
It is a protocol of the full duplex communication over a single TCP connection, WebSocket
a communication protocol specified by the IETF in 2011 as a standard RFC 6455
by RFC7936
supplementary specifications.
WebSocket
So that data exchange between the client and the server easier, use WebSocket
the API only need to complete one 握手
directly can create a persistent connection and two-way data transmission.
WebSocket
Supported clients are not limited to 浏览器
(Web application), many customers in the App end of today's application market push service has a long connection is based mostly WebSocket
to interact agreement.
Websocket
Since the upgrade from the HTTP protocol, at the beginning of interaction of the protocol HTTP is required according to the normal process. Thus, Websocket can be easily established communication based on SSL encryption technology.
protocol
WebSocket
Similar to the HTTP protocol to achieve slightly different but also mentioned earlier: WebSocket
the agreement before making the need for interaction 握手
, 握手协议
interaction is to use HTTP协议
upgraded from.
As we all know, HTTP protocol is a stateless protocol. For this based 请求->回应
on the mode of connection, even in HTTP/1.1
the specification achieved Keep-alive
can not avoid this problem.
Therefore, Websocket
by HTTP/1.1
agreement of 101
the protocol negotiated to upgrade the status code, under the conditions of the protocol supported by the server upgrade will respond to the request to complete the upgrade HTTP->TCP
of 协议升级
.
principle
The client after TCP3 handshake after sending an HTTP upgrade connection request that includes not only the HTTP header information needed to interact, but also includes Websocket
interactive unique encrypted information.
When the server receives the client's request to upgrade the agreement, the actual situation of various types of Web service implementation, the request for which version of encrypted information, details of agreements upgrade judge. Error (invalid) information will be rejected.
After confirming the completion of both ends of the interaction, the two sides interact agreement will abandon from the original HTTP protocol instead use Websocket
a unique protocol interaction. Protocol specification may refer to the RFC .
Advantage
The need to push the message, the connection remains, interactive efficiency requirements, changing the two protocols will bring a different way of interacting.
First, Websocket
the protocol header compression technique used to compress the head and contains 2-10 byte size data payload length, which significantly reduces the overhead network interaction and ensures data integrity information.
If we assume that in a stable (possible) network environment will reduce the overhead of establishing a connection, authentication, and so bring the network overhead as much as possible, while than have HTTP
a more convenient way protocol packet analysis.
Secondly, because the basis Websocket
of agreement in 请求->回应
the bi-directional, so it will not clog the case of multiple requests appear connected. It also greatly reduces the extent of the problems delayed the normal request.
Finally, Websocket
also giving developers the ability to control more of the connection: connection timed out, heartbeat judgment under reasonable connection management plan, which can provide users with better development programs.
API
cf framework httpd
library built Websocket
routing, provided the above-described Websocket
connection management capabilities.
Websocket
Routing requires developers to provide a version of lua class
object to abstract the process of routing process, such abstraction can simplify the coding difficulty.
lua class
class
Paraphrase 'class' is an abstract description of 'Object' and used for a variety of object-oriented programming language. Lua no native class
type, but provide the basic building element method.
cf for convenience of description and built-in library package built-in objects, to establish a basic model class associated element method using the lua table. rely almost most cf the built-in library class library.
Meanwhile, in order to simplify class
. Learning costs, in addition to class originally owned by 'multiple inheritance' concept which is only 类
defined for the completion of the class
-> object
initialization work.
More about class
details, please refer to the Wiki on class
library documents .
Websocket related API
Now we start learning Websocket
associated with API
WebSocket:ctor(opt)
Websocket initialize the object, Websocket client connection is established to be called before completion.
This method is called before on_open method is generally used to tell httpd
how how data packets interaction.
function websocket:ctor (opt)
self.ws = opt.ws -- websocket对象
self.send_masked = false -- 掩码(默认为false, 不建议修改或者使用)
self.max_payload_len = 65535 -- 最大有效载荷长度(默认为65535, 不建议修改或者使用)
end
复制代码
WebSocket:on_open()
After the completion of this connection initialization method is called. Although this method Websocket:ctor
, but generally only when using a similar service for internal initialization.
function websocket:on_open()
local cf = require "cf"
self.timer = cf.at(0.01, function ( ... ) -- 启动一个循环定时器
self.count = self.count + 1
self.ws:send(tostring(self.count))
end)
end
复制代码
WebSocket:on_message(data, type)
When this method sends text / binary data in the user is called back.
Parameter is a string type of data playload; type is a boolean variable, true for the binary type, text type otherwise.
function websocket:on_message(data, typ)
print('on_message', self.ws, data, typ)
self.ws:send('welcome')
-- self.ws:close(data)
end
复制代码
WebSocket:on_error(error)
This method is called back when the protocol error with an unknown error occurred, error parameter is a string type of error message.
Normally we do not use this method.
function websocket:on_error(error)
print('on_error:', error)
end
复制代码
WebSocket:on_close(data)
This callback method when the connection is closed. Transmits data over the data connection is closed, it is possible for the data nil
.
Whatever the case, when the connection is closed all will call this method, but this method is usually the role of cleaning up the data.
function websocket:on_close(data)
if self.timer then -- 清理定时器
print("清理定时器")
self.timer:stop()
self.timer = nil
end
end
复制代码
More API
More about Websocket
the API Wiki, please refer to the documentation .
Start practice
Establish a route
! Let us in script
the new two files in the directory: main.lua
and ws.lua
then fill in respectively the following:
-- app/script/ws.lua
local class = require "class"
local ws = class("websocket")
function ws:ctor(opt)
self.ws = opt.ws
self.send_masked = false
self.max_payload_len = 65535
end
function ws:on_open()
end
function ws:on_message(data, typ)
end
function ws:on_error(error)
end
function ws:on_close(data)
end
return ws
复制代码
-- main.lua
local httpd = require "httpd"
local app = httpd:new("httpd")
app:ws('/ws', require "ws")
app:listen("", 8080)
app:run()
复制代码
We use the httpd
library started a Web Server, while ws.lua
in the class
registration object Websocket
to be processed.
At the same time, we have Websocket:ctor
internal methods for routing the connection initialization Websocket some connection information. The above is the most streamlined Websocket routes.
Start writing a simple Demo
First, we ws:on_open
add a piece of code inside the method timer, the timer continued to push for incremental news to developers after the connection is established.
function ws:on_open()
local cf = require "cf"
local count = 1
self.timer = cf.at(3, function(...)
self.ws:send(tostring(count))
count = count + 1
end)
print(self.ws, "客户端连接成功.")
end
复制代码
Then, we ws:on_close
way to add some code to prevent the destruction of timer memory leaks.
function ws:on_close(data)
if self.timer then
self.timer:stop()
self.timer = nil
end
print(self.ws, "客户端关闭了连接.")
end
复制代码
Finally, the implementation of a message sent by the client once for each echo response.
function ws:on_message(data, type)
self.ws:send(data, type)
print(self.ws, "接受到客户端发送的消息.", data)
end
复制代码
Run cfadmin
,
Let's use chrome browser click here , using the extraction code cgwr
download Websocket
client plug-in and install it.
Then open just downloaded websocket client plug-in and its Websocket Address
input connected to address our connection and view the push message service side.
Developers can run in cfadmin
to view the connection establishment message printing terminal.
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin
[2019/06/18 21:48:36] [INFO] httpd正在监听: 0.0.0.0:8080
[2019/06/18 21:48:36] [INFO] httpd正在运行Web Server服务...
[2019/06/18 21:48:39] - ::1 - ::1 - /ws - GET - 101 - req_time: 0.000080/Sec
websocket-server: 0x7f9495e01200 客户端连接成功.
websocket-server: 0x7f9495e01200 接受到客户端发送的消息. hello world
websocket-server: 0x7f9495e01200 客户端关闭了连接.
复制代码
The full code
-- main.lua
local httpd = require "httpd"
local app = httpd:new("httpd")
app:ws('/ws', require "ws")
app:listen("", 8080)
app:run()
复制代码
-- app/script/ws.lua
local class = require "class"
local ws = class("websocket")
function ws:ctor(opt)
self.ws = opt.ws
self.send_masked = false
self.max_payload_len = 65535
end
function ws:on_open()
local cf = require "cf"
local count = 1
self.timer = cf.at(3, function(...)
self.ws:send(tostring(count))
count = count + 1
end)
print(self.ws, "客户端连接成功.")
end
function ws:on_message(data, type)
self.ws:send(data, type)
print(self.ws, "接受到客户端发送的消息.", data)
end
function ws:on_error(error)
end
function ws:on_close(data)
if self.timer then
self.timer:stop()
self.timer = nil
end
print(self.ws, "客户端关闭了连接.")
end
return ws
复制代码
Continue studying
The next chapter we will learn cf framework built-in asynchronous library
Reproduced in: https: //juejin.im/post/5d09ccb06fb9a07ee27b1939