c++ - Socket.io Client C++, get array from socket.on
问题描述
I'm building an implementation of Socket.io client for C++ able to manage an array of objects at same time, I have a Node.JS server configured like this to send an Array of objects in JSON Format
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var numeroconectados = 0;
var booleano = 0;
var valormotor = 0,
valorled = 0,
valorpiston = 0,
valorultrasonico = 0;
app.get('/', function(req, res) {
res.sendFile(__dirname + '/public/index.html');
});
io.on('connection', function(socket) {
numeroconectados += 1;
socket.emit('inicializar', {
'led': valorled,
'piston': valorpiston,
'motor': valormotor,
'ultrasonico': valorultrasonico
});
console.log("<<Usuario conectado>> Usuarios en linea: " + numeroconectados);
socket.on('disconnect', function() {
numeroconectados -= 1;
console.log('<<Usuario desconectado>> Usuarios en linea: ' + numeroconectados);
});
socket.on("datos", function(data) {
var sizedatos = data.length;
console.log(sizedatos);
for (i = 0; i < sizedatos; i++) {
console.log("Nombre: " + data[i].nombre + " Tipo: " + data[i].tipo +
" Valor: " + data[i].valor);
if(data[i].tipo == 'motor') valormotor = data[i].valor;
if(data[i].tipo == 'led') valormotor = data[i].valor;
if(data[i].tipo == 'ultrasonico') valormotor = data[i].valor;
if(data[i].tipo == 'piston') valormotor = data[i].valor;
}
socket.broadcast.emit('datos', data); //Envia a todos los clientes
});
/*socket.on('motor', function(msg) {
console.log('motor ' + msg);
valormotor = msg;
socket.broadcast.emit('motor', msg);
});
socket.on('led', function(msg) {
valorled = msg;
console.log('led ' + msg);
socket.broadcast.emit('led', msg);
});
socket.on('ultrasonico', function(msg) {
valorultrasonico = msg;
console.log('ultrasonico ' + msg);
socket.broadcast.emit('ultrasonico', msg);
});
socket.on('piston', function(msg) {
valorpiston = msg;
console.log('piston ' + msg);
socket.broadcast.emit('piston', msg);
});*/
});
http.listen(3000, function() {
console.log('listening on *:3000');
});
I have an object to store data, to improve responsiveness of the system send a vector of objects when some of them had changed. In my C++ program I receive the result array of objects in JSON, for that I have the code
#include "sio_client.h" //Librería de Sockets io
#include <functional> //Librerías estándar
#include <iostream>
#include <thread> //Librerías de Multriprocesamiento
#include <mutex>
#include <condition_variable>
#include <string> //Librerías de cadena de caracteres
#include <sstream>
#define HIGHLIGHT(__O__) std::cout<<"\e[1;31m"<<__O__<<"\e[0m"<<std::endl //Colorear las funciones
#define EM(__O__) std::cout<<"\e[1;30;1m"<<__O__<<"\e[0m"<<std::endl
using namespace sio; //Workspace de Sockets.io
using namespace std; //Workspace de std
std::mutex _lock; //Workspace de multithreading
std::condition_variable_any _cond;
bool connect_finish = false;
/*
* Clase para conectar el listener, para aguardar por eventos
*/
class connection_listener {
sio::client &handler;
public:
connection_listener(sio::client& h) :
handler(h) {
}
void on_connected() {
_lock.lock();
_cond.notify_all();
connect_finish = true;
_lock.unlock();
std::cout << "Servidor conectado correctamente" << std::endl;
}
void on_close(client::close_reason const& reason) {
std::cout << "sio closed " << std::endl;
exit(0);
}
void on_fail() {
std::cout << "sio failed " << std::endl;
exit(0);
}
};
socket::ptr current_socket; //Api de socket
string mensaje;
void eventos() {
std::cout << "Inicio de recepcion de datos" << std::endl;
std::vector<std::shared_ptr < message>> hola;
current_socket->on("datos", sio::socket::event_listener_aux([&](string
const& name, message::ptr const& data, bool isAck, message::list & ack_resp) {
_lock.lock(); //Bloquear la ejecucion hasta realizar una opcion
hola = data -> get_vector();
for (int i = 0; i < hola.size(); i++) {
std::cout << hola.at(i)->get_map()["tipo"]->get_string() << std::endl;
std::cout << hola.at(i)->get_map()["nombre"]->get_string() << std::endl;
std::cout << hola.at(i)->get_map()["tipo"]->get_string() << std::endl;
std::cout << hola.at(i)->get_map()["valor"]->get_string() << std::endl;
}
_lock.unlock(); //Desbloquear la ejecucion para seguir con el programa
}));
}
//Separar string con delimitador
std::vector<std::string> split(std::string strToSplit, char delimeter) {
std::stringstream ss(strToSplit);
std::string item;
std::vector<std::string> splittedStrings;
while (std::getline(ss, item, delimeter)) {
splittedStrings.push_back(item);
}
return splittedStrings;
}
int main(int argc, const char* args[]) {
sio::client h; //Creación de un nuevo cliente de Sockets.io
connection_listener l(h); //Añado al cliente un listener para obtener eventos
h.set_open_listener(std::bind(&connection_listener::on_connected, &l));
h.set_close_listener(std::bind(&connection_listener::on_close, &l, std::placeholders::_1));
h.set_fail_listener(std::bind(&connection_listener::on_fail, &l));
h.connect("http://127.0.0.1:3000"); //Conexión al servidor Web
_lock.lock();
if (!connect_finish) {
_cond.wait(_lock);
}
_lock.unlock();
current_socket = h.socket(); //Socket para inicio de dato
//Separar string
std::vector<std::string> cadenaseparada;
int numeroentrada = 0;
string identificador;
int opcion = 20;
eventos(); //mandar a llamar una vez, obligatorio
for (std::string line; std::getline(std::cin, line);) {
if (line.length() > 0) {
if (line == "$exit") {
std::cout << "Salir" << std::endl;
break;
} else if (line.length() > 4 && line.length() < 15) {
cadenaseparada = split(line, ',');
identificador = cadenaseparada[0];
mensaje = cadenaseparada[1];
current_socket->emit(identificador, mensaje);
_lock.lock();
std::cout << "Identificador: " << identificador << std::endl << "Mensaje: " << mensaje << std::endl;
_lock.unlock();
} else {
std::cout << "Evento desconocido" << std::endl;
}
}
}
h.close(); //Cerrar servidor
return 0;
}
I convert the message::ptr const& data
received from current_socket -> on
method to std::vector with the method hola = data -> get_vector();
(hola is a std::vector<std::shared_ptr < message>>
), but when I want to access the array I get a SIGSEGV error. I wonder if I defined a bad structure for std::vector> hola, any help is aprecciated, thanks
解决方案
Put the definition of hola
vector into lambda.
_lock.lock(); //Bloquear la ejecucion hasta realizar una opcion
std::vector<std::shared_ptr < message>> hola = data -> get_vector();
Now, in eventos
function you create lambda which captures all local variables by reference ( [&] ), so your lambda holds reference to hola
vector. hola
vector is destroyed when eventos
function terminates. You get segmentation fault because your lambda is called outside eventos
function, and you try to assign data -> get_vector();
vector to hola
object which doesn't exist.
推荐阅读
- terraform - aws_rds_cluster_instance 资源提升为 create-before-destroy 尽管生命周期将其设置为 false
- flutter - 必须初始化不可为空的实例字段“verificationId”
- python - 使用 BeautifulSoup 在没有类名的范围内提取文本
- django - Django 是否支持类似于 models.TextChoices 的模型字段的整数枚举?
- python - 如何从具有限制的不同数据帧中填充数据帧 nan 值?
- python - xarray groupby 坐标和非坐标变量
- python - 如何使用 matplotlib python 添加颜色图和矩形框?
- python - 在此处进行更改,以使程序适用于更长的输入
- c# - C# RDLC 报告查看器 LocalReport 执行崩溃
- node.js - 让 REACT 应用程序在端口 3001 上运行以显示在 AWS EC2 Http 端口 80 上