В рамках прототипа, над которым я работал, у меня была возможность опробовать протоколы буферов для сквозного сценария. Поскольку мне приходилось собирать фрагменты информации из разных источников, чтобы заставить ее работать, я подумал, что было бы полезно собрать ее в одном сообщении. Вот оно.

Буферы протокола

Буферы протокола предоставляют альтернативу JSON (и аналогичным форматам) для обмена сообщениями. Они используются для описания протокола в файлах .proto, а компилятор буферов протокола (protoc) используется для компиляции этих файлов в оболочки для различных языков программирования (C ++, C # , Java, JavaScript и т. Д.) Для использования описываемого протокола. Подробная информация о буферах протокола представлена ​​в документации Google:



Для целей этого блога давайте определим простое сообщение в testmessage.proto:

syntax = "proto3";
message TestMessage {
    string someText = 1;
}

Чтобы сгенерировать оболочки JavaScript для этого протокола, загрузите компилятор протоколов буферов отсюда и разархивируйте его:



Теперь запустите эту команду, чтобы сгенерировать оболочку testmessage_pb.js:

$ protoc --js_out=import_style=commonjs,binary:. testmessage.proto

Эту оболочку нужно будет скопировать как в клиентский, так и в серверный код.

Сервер

Сервер будет реализован с использованием Express и WebSockets, и мы также будем использовать буферы протокола. Итак, эти зависимости необходимо будет установить:

$ npm install express ws google-protobuf

Поскольку мы хотим использовать HTTPS, мы будем использовать самозаверяющие сертификаты. Чтобы сгенерировать сертификаты, используйте эту команду:

$ openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
Generating a 2048 bit RSA private key
…………………………………+++
…………………………………………………..+++
writing new private key to ‘key.pem’
Enter PEM pass phrase:
Verifying — Enter PEM pass phrase:
 — — -
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
 — — -
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:WA
Locality Name (eg, city) []:Seattle
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Test
Organizational Unit Name (eg, section) []:Engineering
Common Name (e.g. server FQDN or YOUR name) []:Admin
Email Address []:[email protected]

Я использовал «тест» в качестве пароля. Также можно удалить парольную фразу из сертификата, но это всего лишь дополнительный шаг. Для простоты я просто добавлю парольную фразу в код. Файлы key.pem и cert.pem необходимо скопировать в код сервера.

Вот фрагмент кода для сервера:

'use strict'
const TestMessage = require('./testmessage_pb')
const Express = require('express')
const Https = require('https')
const WebSocket = require('ws')
const FileSystem = require('fs')
const app = Express()
app.use(function (req, res) {
    res.send({ msg: 'hello' })
})

const server = Https.createServer({
    key: FileSystem.readFileSync('key.pem'),
    cert: FileSystem.readFileSync('cert.pem'),
    passphrase: 'protobufjstest'
}, app)
const wss = new WebSocket.Server({ server })
wss.on('connection', function connection(ws) {
    ws.on('message', function incoming(message) {
        console.log('received: %s', message)
    })
    var message = new proto.TestMessage();
    message.setSometext('Hello Protocol Buffers')
    
    var bytes = message.serializeBinary()
    ws.send(bytes)
})
server.listen(7070, function listening() {
    console.log('Listening on %d', server.address().port)
})

Клиент

Теперь, когда у нас есть сервер, мы реализуем клиента. Клиенту нужно будет использовать WebSockets и Protocol Buffers. Итак, нам нужно будет установить эти зависимости:

$ npm install ws google-protobuf

Вот фрагмент кода для клиента:

'use strict'
const TestMessage = require('./testmessage_pb')
const WebSocket = require('ws')
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
const ws = new WebSocket('wss://localhost:7070/', {
    origin: 'https://localhost:7070'
})
ws.on('open', function open() {
    console.log('connected')
})
ws.on('close', function close() {
    console.log('disconnected')
})
ws.on('message', function incoming(data, flags) {
    console.log('message')
    var bytes = Array.prototype.slice.call(data, 0)
    var message = proto.TestMessage.deserializeBinary(bytes)
    console.log(message.getSometext())
    ws.close()
})

Выход

После того, как сервер и клиент реализованы, давайте попробуем. Сначала запустим сервер:

$ node server.js 
Listening on 7070

Далее мы подключим клиента к серверу:

$ node client.js 
connected
message
Hello Protocol Buffers
disconnected

И сообщение от сервера к клиенту успешно передается с использованием буферов протокола! Это был простой пример, демонстрирующий буферы протокола с WebSockets через HTTPS в Node.js / Express. Надеюсь, это было полезно.

Вот пример кода:

Https://github.com/ahmadbilal/protobufjstest