This article introduces socket in depth. i/O related information, which has previously been introduced to socket. i/O basic tutorials and applications. This article provides a more in-depth introduction to socket. i/O usage. For more information, see. This article introduces socket in depth. i/O related information, which has previously been introduced to socket. i/O basic tutorials and applications. This article provides a more in-depth introduction to socket. i/O usage. For more information, see.
Preface
Socket. io provides real-time event-based two-way communication. This article introduces socket. io in depth. Let's take a look at the details below.
Static files
By default, socket. io uses the socket. io-client package to provide socket. io. min. js and socket. io. js. map downloads.
Run the instance app. js
let app = require('http').createServer() let io = require('socket.io')(app)app.listen(3000);
The browser accesses http: // localhost: 3000/socket. io/socket. io. js can load the compressed source code and access http: // localhost: 3000/socket. io/socket. io. js. map loads sourcemap
We can change this behavior.
Disable socket. io. js download
Method 1: Pass in the control parameter serveClient value false during instantiation
let io = require('socket.io')(app, { serveClient: false})
Method 2: Call the serverClient Function
Let app = require ('HTTP '). createServer () let io = require ('socket. io ') () io. serveClient (false) io. listen (app) // Or io. attach (app)
If the service is bound before the function is calledhttp.Server
, This method will not work
A prompt is displayed when you access the service again after it is disabled.{"code":0,"message":"Transport unknown"}
Modify static file path
The path of socket. io. js can be changed. The default path is/socket. io.
Parameter passing during instantiation
let io = require('socket.io')(app, { path: '/io'})
Call the function path
let app = require('http').createServer() let io = require('socket.io')() io.path('/io') io.listen(app)
If the service is bound before the function is calledhttp.Server
, This method will not work
Security Policy
Socket. io provides two security policies
AllowRequest
The allowRequest function has two parameters. The first parameter is the received handshake packet (http.request
) Object as the judgment basis, success), err is the error object, success is boolean, false indicates that connection establishment is blocked
Front-end request with token
let socket = io('http://localhost:3000?token=abc') socket.on('connect', () => { console.log('connect')})socket.on('connect_error', err => { socket.disconnect() console.log('connect_error', err)})
Backend allowRequest determines whether to continue based on the token
let app = require('http').createServer() let io = require('socket.io')(app, { allowRequest: (req, cb) => { if (req._query && req._query.token === 'abc') return cb(null, true) cb(null, false) }});
Origins
You can restrict the source
1. The time limit for instantiation is origin
let app = require('http').createServer() let io = require('socket.io')(app, { origins: 'http://localhost:3000'})
2. Set the source using the origins Function
The origins function has two forms:
origins(string)
: Set the running Source
origins(string, fn(err, success))
: Use a function to determine whether the source is allowed
io.origins('http://localhost:*')io.origins((origin, cb) => { if (origin === 'http://localhost:3000/') return cb(null, true) cb(null, false)})
Namespace
Namespaces are used to isolate connections between the server and client. In some cases, namespaces are called channels ). The following is an example of its meaning.
We need to implement a collaborative application, which has two functions:
This application is implemented using socket. io in the following forms:
1. Completely independent: Collaborative Editing has an independent serviceedit.socket.test
Is an independent service of the message system.message.socket.test
let editSocket = io('edit.socket.test') let messageSocket = io('message.socket.test')
2. namespace: runs only one independent service and is isolated through namespace
Let app = require ('HTTP '). createServer () let io = require ('socket. io ') (app) let editServer = io. of ('/edit') let messsageServer = io. of ('/message') editServer. on ('connection', socket =>{// edit related}) messsageServer. on ('connection', socket =>{/ message related })
let editSocket = io('socket.test/edit') let messageSocket = io('socket.test/message')
3. event name conventions: isolate by adding event names
Let app = require ('HTTP '). createServer () let io = require ('socket. io ') (app) io. on ('connection', socket => {// edit related io. emit ('edit: test') io. on ('edit: test', data =>{}) // message-related io. emit ('message: test') io. on ('message: test', data => {})}
The procedure defined by the event name is too invasive, which is not conducive to splitting and restructuring and is not recommended. The completely independent mode requires two socket connections, that is, the number of concurrent connections allowed by the browser is wasted, and more server resources are consumed. Namespace can achieve good isolation without wasting resources.
Default namespace
When socket. io is instantiated, it is automatically bound to the/namespace path.
Let app = require ('HTTP '). createServer () let io = require ('socket. io ') (app) io. sockets // io. of ('/'). sockets io. emit // proxy io. of ('/'). emit, similar functions include 'to', 'in', 'use', 'send', 'write', 'clients ', and 'compress'
Middleware
The socket. io namespace registers the middleware through use. After the middleware establishes a connection between the client and the server, it is called once before the connet event is distributed.
Use middleware data verification
io.use((socket, next) => { if (socket.request.headers.cookie) return next() next(new Error('Authentication error'))})
Extract or convert data Using Middlewareio.use((socket, next) => {
getInfo(socket.request.query.id, (err, data) => { if (err) return next(err) socket.custom = data next() }) })
Comparison with allowRequest
AllowRequest can be used for some verification and extraction. Why does it need middleware?
The http. request instance passed in by allowRequest, while the middleware accesses and exits the data socket instance. The socket instance contains the request instance and has more information.
Middleware directly supports multiple asynchronous process nesting, while allowRequest needs to be implemented by itself
Comparison with connection events
The connection event is also passed into the socket, which can also be used for data verification and extraction. Why do we need middleware?
Middleware directly supports multiple asynchronous process nesting, while allowRequest needs to be implemented by itself
After the middleware succeeds, socket. io also performs some work before the connection event is successfully sent, such as adding the socket instance to the connected object and joining the chat room. If the connection is interrupted due to permission interruption, the middleware can process more resources.
Chat Room
The chat room groups the socket set currently connected according to specific rules to facilitate group messaging. Similar to the probability of a QQ group.
Socket. join ('room name') // enter socket. leave ('room name') // exit
Io. to ('some room'). emit ('some event') // io. to is synonymous with io. in and sends messages to all Members in a chat room.
Default chat room
Each socket automatically creates a default chat room after the connection is successful. The name of the chat room is the id of the current socket. You can use the default chat room to send messages to specific users.
socket.on('say to someone', (id, msg) => { socket.broadcast.to(id).emit('my message', msg)})
Message sending
Response Message
A common message does not need a response, but a response mechanism is provided for the response message.
Io. on ('connection', socket => {socket. emit ('an event', {some: 'data'}) // common message socket. emit ('ferret ', 'tobi', function (data) {// Response Message console. log (data); // data will be 'woot '})})
socket.on('ferret', (name, fn) => { fn('woot')})
Compression
socket.compress(true)
Enable compression. After the call, all data of the current connection will be compressed before being passed to the client.
Volatile flag
Under normal circumstances, socket. io tracks the sent messages to ensure that the messages are successfully sent. When volatile is set to send messages, socket. io does not track the messages, and the messages may be lost.
Category
// The client sends the socket. emit ('hello', 'Can you hear me? ', 1, 2, 'abc'); // send the socket. broadcast. emit ('broadcast', 'Hello friends! '); // Send a message to the game chat room, which is not counted as a socket. to ('game '). emit ('Nice game', "let's play a game"); // send messages to the game1 and game2 chat rooms at the same time. It is not a socket. to ('ame1 '). to ('game2 '). emit ('Nice game', "let's play a game (too)"); // send the message io to the game chatroom owner. in ('game '). emit ('big-announcement ', 'the game will start soon'); // send the message
Client socket. (
). Emit ('Hey ',' I just met you '); // send the Response Message socket. emit ('Question', 'Do you think so? ', Function (answer ){});
The preceding section describes socket. io in node. js (3). For more information, see other related articles in the first PHP community!