bool ServidorDeConexion::inicializar (const unsigned short puerto, std::shared_ptr<TablaDeClientes> destino)
{
	//Si ya está inicializado, primero cierra el socket previo
	if (estaInicializado())
	{
		close(descriptor_socket_escucha_);
		descriptor_socket_escucha_ = -1;
	}
	
	//Se rellenan los datos de conexión necesarios para crear un socket
	struct addrinfo indicaciones;
	struct addrinfo *info_servidor;
	string cad_puerto = to_string(puerto);
	
	memset(&indicaciones, 0, sizeof(struct addrinfo));
	indicaciones.ai_family = AF_UNSPEC;
	indicaciones.ai_socktype = SOCK_STREAM;
	indicaciones.ai_flags = AI_PASSIVE;
	
	//Si no se consigue obtener información de dirección válida para el servidor, se termina con error
	if (getaddrinfo(nullptr, &cad_puerto[0], &indicaciones, &info_servidor) != 0) return false;
		
	//Se recorren los resultados obtenidos creando y asociando el socket a la primera dirección posible
	for (struct addrinfo *p = info_servidor; p != nullptr; p = p->ai_next)
	{
		descriptor_socket_escucha_ = socket (p->ai_family, p->ai_socktype, p->ai_protocol);
		if (descriptor_socket_escucha_ >= 0)
		{	
			//Si se ha encontrado una dirección válida, se establecen las opciones del socket
			int si = 1;
			if (setsockopt(descriptor_socket_escucha_, SOL_SOCKET, SO_REUSEADDR, &si, sizeof(int)) < 0)
			{				
				//Si esta operación falla, se devuelve error
				freeaddrinfo(info_servidor);
				close(descriptor_socket_escucha_);
				descriptor_socket_escucha_ = -1;
				return false;
			}
			
			//Se asocia el socket a la dirección encontrada
			if (bind(descriptor_socket_escucha_, p->ai_addr, p->ai_addrlen) >= 0)
			{
				//En caso de que todo haya ido correctamente, se guarda la tabla de clientes y se termina
				freeaddrinfo(info_servidor);
				clientes_ = destino;
				return true;
			}
			
			//Si ha fallado la asociación del socket a la dirección, se cierra el socket y se sigue buscando
			close(descriptor_socket_escucha_);
		}
	}
	
	//Si se ha llegado a este punto, no se ha conseguido conectar a ninguna dirección válida
	freeaddrinfo(info_servidor);
	return false;
}
bool ServidorDeConexion::recibirClientes (void)
{
	//Se chequea si el servidor ha sido ya correctamente inicializado y dispone de un socket operativo
	if (!estaInicializado()) return false;
	
	//El servidor comienza a escuchar en el socket
	if (listen(descriptor_socket_escucha_, MAX_PENDIENTES_) < 0) return false;
		
	//Se crea un nuevo hilo para obtener nuevos clientes
	thread hilo_servidor ([]
		(const int descriptor_socket_escucha, weak_ptr<TablaDeClientes> clientes)
		{
			//En el hilo, se crea un bucle que obtiene nuevos clientes y los añade a los ya existentes
			shared_ptr<TablaDeClientes> sp_clientes;
			int socket_nuevo_cliente;
			struct sockaddr_storage direccion_nuevo_cliente;
			socklen_t tamano_direccion = sizeof(struct sockaddr_storage);
			bool terminar = false;
			while (!terminar)
			{
				socket_nuevo_cliente = accept (	descriptor_socket_escucha,
												(struct sockaddr *)& direccion_nuevo_cliente,
												&tamano_direccion	);
				if (socket_nuevo_cliente >= 0)
				{
					sp_clientes = clientes.lock();
					if (!sp_clientes) terminar = true;
					else sp_clientes->anadirCliente(socket_nuevo_cliente);
					sp_clientes.reset();
				}
				else terminar = true;
			}
			
		}, descriptor_socket_escucha_, clientes_);
		
	//Se desvincula del hilo servidor y termina con éxito
	hilo_servidor.detach();
	return true;
}
Ejemplo n.º 3
0
std::string Simbolo::toString(void) const
{
    std::stringstream dimensiones;
    dimensiones << _cantDimensiones;
    std::string tipo = getStringTipo();
    std::stringstream tRetorno;

    std::stringstream valor;

    if(_tipo == T_FUNCION)
    {
        valor << "FUNCION";
        switch(_retorno)
        {
            case T_ENTERO:
                tRetorno << "Entero";
                break;
            case T_REAL:
                tRetorno << "Real";
                break;
            case T_BOOLEANO:
                tRetorno << "Logico";
                break;
            case T_CADENA:
                tRetorno << "Alfabetico";
                break;
            case T_CARACTER:
                tRetorno << "Caracter";
                break;
            default:
                tRetorno << "Void";
                break;
        }
    }
    else if(_ptr == NULL || !estaInicializado())
    {
        valor << "NULO";
    }
    else
    {
        switch(_tipo)
        {
            case T_ENTERO:
                valor << this->getValor<int>();
                break;
            case T_REAL:
                valor << this->getValor<double>();
                break;
            case T_BOOLEANO:
                valor << this->getValor<bool>();
                break;
            case T_CADENA:
                valor << (this->getValor<std::string>());
                break;
            case T_CARACTER:
                valor << this->getValor<char>();
                break;
            default:
                valor << "NULO";
                break;
        }
    }

    return "ID: " + _identificador + " Tipo: " + tipo + " Const: " + (_constante ? "Si" : "No") + " Temp: " + (_temporal? "Si":"No") +" Dimen: " + dimensiones.str() +
            " Inicializado: " + (_inicializado ? "Si":"No") + " Valor: " + valor.str() + " Retorno: " + tRetorno.str() + " Firma: " + _firma + " Alias: " + _alias;
}