我在使用写入和读取功能与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
答案 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()是类似的。
答案 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));