【问题标题】:Socket.io Client C++, get array from socket.onSocket.io Client C++,从 socket.on 获取数组
【发布时间】:2018-07-12 17:05:25
【问题描述】:

我正在构建一个能够同时管理对象数组的Socket.io client for C++ 的实现,我有一个这样配置的 Node.JS 服务器以发送 JSON 格式的对象数组

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');
});

我有一个对象来存储数据,以提高系统的响应能力,当其中一些对象发生变化时发送一个对象向量。在我的 C++ 程序中,我收到 JSON 格式的对象的结果数组,因为我有代码

#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;
}

我使用hola = data -&gt; get_vector(); 方法将从current_socket -&gt; on 方法接收到的message::ptr const&amp; data 转换为std::vector(hola 是std::vector&lt;std::shared_ptr &lt; message&gt;&gt;),但是当我想访问该数组时,我得到一个SIGSEGV 错误。我想知道我是否为 std::vector> hola 定义了一个错误的结构,感谢任何帮助,谢谢

【问题讨论】:

    标签: c++ vector websocket socket.io segmentation-fault


    【解决方案1】:

    hola向量的定义放入lambda中。

        _lock.lock(); //Bloquear la ejecucion hasta realizar una opcion
        std::vector<std::shared_ptr < message>> hola = data -> get_vector();
    

    现在,在 eventos 函数中,您创建 lambda,它通过引用 ( [&] ) 捕获所有局部变量,因此您的 lambda 持有对 hola 向量的引用。当eventos 函数终止时,hola 向量被破坏。您会遇到分段错误,因为您的 lambda 在 eventos 函数之外被调用,并且您尝试将 data -&gt; get_vector(); 向量分配给不存在的 hola 对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-12
      • 2021-04-21
      • 2013-11-05
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 2018-08-27
      相关资源
      最近更新 更多