使用对象编写和读取函数 - C ++

时间:2015-11-15 02:19:44

标签: c++

我在使用写入和读取功能与FIFO文件进行交互时遇到了一些问题,出于某种原因,当我读取FIFO时,我在readed对象中得到了垃圾(我做了一个minitwitter,所以使用客户端 - 服务器模型):

客户端:

Breakpoint 1, main (argc=3, argv=0x7fffffffdf88) at Cliente.cpp:50
50      if(write (fdReceiverPipe, registerMessage, sizeof (*registerMessage)) == -1){
(gdb) p registerMessage
$3 = (Mensaje *) 0x605030
(gdb) p *registerMessage
$4 = {sender = 1, mensaje = "21870", tipoRequest = 0}

服务器端:

Breakpoint 1, MessagePipeHandler (
messageRequestCounter=0x606324 <messageRequestCounter>) at Gestor.cpp:166
166       int statusMessagePipe = read (fdMessagePipe, mensaje, sizeof *mensaje);
(gdb) p sizeof (mensaje)
$1 = 8
(gdb) p sizeof (*mensaje)
$2 = 24
(gdb) p *mensaje
$3 = {sender = -144108792, mensaje = "", tipoRequest = 6320304}

为了避免垃圾进入管道,客户端到服务器管道O_NONBLOCK选项是清除的,服务器发送信号时会重命名服务器到客户端管道,这里是代码:

服务器端:

//Function for pipe for messages check and processing
void MessagePipeHandler (int *messageRequestCounter) {
  //Open the message pipe
  std :: cout << "Abriendo pipe " << mainPipeName << std :: endl;
  int fdMessagePipe = open (mainPipeName, O_RDONLY);
  if (fdMessagePipe == -1) {
    std :: cout << "No se pudo abrir el pipe para los mensaje, ¿Existe el archivo del pipe?" << std :: endl;
    exit (EXIT_FAILURE);
  } else {
    //Activate message pipe service
    std :: cout << "¡Servicio de pipe de mensajes online!" << std :: endl;
    int statusMessagePipe;
    while (true) {
      Mensaje *mensaje = new Mensaje ();
      int statusMessagePipe = read (fdMessagePipe, mensaje, sizeof (*mensaje));
      if (statusMessagePipe == -1) {
        std :: cout << "Error al leer el archivo de pipe..." << std :: endl;
        exit (EXIT_FAILURE);
      } else if (statusMessagePipe > 0) {
        //Check message type
        switch (mensaje -> getTipoRequest ()) {
          //Connection request
          case 0:
            IDMessageHandler (mensaje);
            break;
          //Follow
          case 1:
            server -> setRelation (mensaje -> getSender (), atoi (mensaje -> getMensaje().c_str()), '1');
            break;
          //Unfollow
          case 2:
            server -> setRelation (mensaje -> getSender (), atoi (mensaje -> getMensaje().c_str()), '0');
            break;
          //Tweet
          case 3:
            DispatchTweet (mensaje);
            break;
          //Disconnect
          case 5:
            server -> Disconnect (mensaje -> getSender ());
            break;
          //Bad request
          default:
            std :: cout << "El tipo de request es desconocido, continuando..." << std :: endl;
            break;
        }
        (*messageRequestCounter) ++;
      }
      mensaje -> Dispose ();
    }
  }
}

客户端:

int main (int argc, char** argv){
    //Installing signal handler
    signal (SIGUSR1, (sighandler_t) signalHandler);
    //See if IDPipe is created
    receiverPipe = argv[2];
    int fdReceiverPipe = open (receiverPipe, O_WRONLY);
    std :: cout << fdReceiverPipe << std :: endl;
    if (fdReceiverPipe > 0) std :: cout << "Pipe de IDs encontrado, registrandose..." << std :: endl;
    else {
        std :: cout << "No se ha encontrado el pipe, ¿esta encendido el servidor?" << std :: endl;
        exit (EXIT_FAILURE);
    }
    //Register the IDs on the pipe
    Mensaje *registerMessage = new Mensaje ();
    std :: ostringstream itos;
    itos << getpid ();
    registerMessage -> setSender (atoi (argv[1]));
    registerMessage -> setMensaje (itos.str ());
    registerMessage -> setTipoRequest (0);
    if(write (fdReceiverPipe, registerMessage, sizeof (*registerMessage)) == -1){
        std :: cout << "Se ha presentado un problema al registrar el cliente." << std :: endl;
        exit (EXIT_FAILURE);
    } else std :: cout << "¡Se ha registrado el cliente con exito!" << std :: endl;
    //Set client info and see server mode
    pause ();
    cliente -> setId (atoi (argv [1]));
    cliente -> setPid (getpid ());
    std :: cout << "Recibida respuesta, obteniendo configuracion del servidor..." << std :: endl;
    Mensaje *serverMessage = new Mensaje ();
    std :: string senderPipe ("SenderPipe");
    std :: string userId (argv [1]);
    senderPipe += userId;
    int fdSenderPipe = open (senderPipe.c_str (), O_RDONLY | O_NONBLOCK);
    if (fdSenderPipe == -1) {
        std :: cout << "No se logro acceder a la configuracion del servidor, ¿esta encendido el servidor?" << std :: endl;
        exit (EXIT_FAILURE);
    } else {
        std :: cout << "Tomando datos del pipe canal, un momento..." << std :: endl;
        for (int tries = 0; tries < MAX_TRIES; tries ++) {
            int pipeState = read (fdSenderPipe, serverMessage, sizeof *serverMessage);
            if (pipeState == -1) {
                std :: cout << "No hay configuracion del servidor, reintentando..." << std :: endl;
                sleep (2000);
            } else {
                if(serverMessage -> getMensaje () == "async") {
                    std :: cout << "Configuracion completada." << std :: endl;
                    Pause();
                    break;
                } else {
                    serverModeAsync = false;
                    std :: cout << "Configuracion completada." << std :: endl;
                    Pause();
                    break;
                }
            }
        }
    }
    std :: cout << "Llamando al menu..." << std :: endl;
    Menu ();
}

我有两个问题: 1)是否可以对二进制文件中的对象I / O操作使用write()和read()? 2)如果没有,是否有任何解决方法,所以我可以维持我使用的OOP?

提前致谢。

修改

消息类:

#ifndef __Mensaje__HXX__
#define __Mensaje__HXX__

#include<iostream>

class Mensaje{
    public:
        Mensaje();
        ~Mensaje();
        int getSender();
        void setSender(int sender);
        std :: string getMensaje();
        void setMensaje(std::string msg);
        int getTipoRequest();
        void setTipoRequest(int tipoRequest);
        void Dispose ();
    private:
        int sender;
        std :: string mensaje;
        int tipoRequest;
};

#include "Mensaje.cxx"

#endif

3 个答案:

答案 0 :(得分:0)

班级Mensaje有一个std::string数据成员。通常,std::string实例是或包含指向字符串缓冲区的指针。将指针发送到另一个进程并尝试在那里使用它是行不通的。

更正式地说,由于not-guaranteed- 标准布局字符串数据成员,Mensaje无法保证标准布局类。

重要的是您发送给其他流程的内容。不要发送指针:发送它指向的文本数据。

答案 1 :(得分:0)

您将此问题标记为C ++。

  

1)是否可以对对象I / O使用write()和read()   二进制文件中的操作? 2)如果没有,是否有任何解决方法,所以我   可以维持我正在使用的OOP吗?

1 - 是的。

2 - 不适用

示例:(下面的read()和write()不是'c'函数)

// m_sIn is std::ifstream
// char*  m_buff
// MAX_buffSz is an enum (in this case)

m_sIn.read (m_buff, MAX_buffSz);

参见def std :: ifstream :: read(char * s,bytecount)

Extracts n characters from the stream and stores them in the array pointed to by s.

This function simply copies a block of data, without checking its contents nor appending a null character at the end.

std :: ofstream :: write()是类似的。

ifstream的read()(和ofstream的write())是二进制i / o。

答案 2 :(得分:0)

好的,我修改了我的Mensaje课程:

#ifndef __Mensaje__HXX__
#define __Mensaje__HXX__

#include<iostream>

class Mensaje{
    public:
        int getSender();
        void setSender(int sender);
        void getMensaje(char message[]);
        void setMensaje(const char *message);
        int getTipoRequest();
        void setTipoRequest(int tipoRequest);
        void Dispose ();
    private:
        int sender;
        char mensaje[141];
        int tipoRequest;
};

#include "Mensaje.cxx"

#endif

遵守POD类的定义:

  

POD结构是一个非联盟类,它既是普通类,又是   标准布局类,并且没有类型为的非静态数据成员   非POD结构,非POD联合(或此类类型的数组)。同样,a   POD联盟是一个既简单又简单的联盟   布局类,并且没有非POD类型的非静态数据成员   struct,非POD联合(或此类型的数组)。 POD类是一个类   这是POD结构或POD联合。   What changes for C++11?: Definition of POD-class

更改I / O函数调用为:

int pipeStatus = write (fdSendingPipe, mensaje, sizeof (Mensaje));
int statusMessagePipe = read (fdMessagePipe, mensaje, sizeof (Mensaje));