从 PIPE 写入和读取结构时出错

Posted

技术标签:

【中文标题】从 PIPE 写入和读取结构时出错【英文标题】:Error writing and reading a structure from PIPE 【发布时间】:2012-05-07 06:34:25 【问题描述】:

我有一个客户端服务器程序,客户端在 PIPE 上为服务器编写命令。从服务器读取命令时,它只读取命令的第一个字符并引发错误。谁能帮我解决这个问题?

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <sys/wait.h>
#include <mqueue.h>
#include <sys/stat.h>
#include "Functions.h"

#define MSGBUFFER_SIZE 50000

pid_t serverPid;
pid_t clientPid;

typedef struct msgbuf 

int messageLength;
int messageType;
char messageText[MSGBUFFER_SIZE];

 Message_buf;

int writePIPE(int fd, Message_buf *inputMessage)

printf("\n In write pipe message length :%d",inputMessage->messageLength);
printf("\n In write pipe message Data :%s",inputMessage->messageText);
ssize_t n=write(fd,inputMessage,inputMessage->messageLength);
printf("\n Size :%d", n);
return n;


ssize_t readPIPE(int fd, Message_buf *outputMessage)

ssize_t len;
ssize_t n;
if((n=read(fd,outputMessage,sizeof(outputMessage)))==0)

    printf("\n Error");
    return 0;

if((len=outputMessage->messageLength)>0)

    printf("\n Length ---->:%d",len);
    if((n=read(fd,outputMessage->messageText,strlen(outputMessage->messageText)))!=len)
        printf("\n ERRRRROR expected %d got %d",len,n);

//printf("\n In Read PIPE: %s",outputMessage->messageText);
return len;

void Server(int readfd,int writefd)

Message_buf server_MessageBuf;

ssize_t length;
if((length=readPIPE(readfd,&server_MessageBuf))==0)

    printf("\n End of file while reading pathname");

//server_MessageBuf.messageText[length]='\0';

printf("\n LENGTH :%d",server_MessageBuf.messageLength);
printf("\n Printing in server: %s\n",server_MessageBuf.messageText);


void Client(int readfd,int writefd)


char inputFileName[MAX_SIZE];
char inputOperation[MAX_SIZE];
char *cCommandInput = NULL;
char *fileOperation = NULL;
char *operation = (char *) malloc(MAX_SIZE);

int commandValidateStatus = 0;
int commandInterpretationStatus=0;
Message_buf client_MessageBuf;
for(;;)

    while(1)
    
        cCommandInput = acceptInput();
        fileOperation = (char *) malloc(sizeof(cCommandInput));
        strcpy(fileOperation,cCommandInput);

        /**Function call to determine operation read/delete/exit/invalid choice and filename*****/
        commandInterpretationStatus = interpretCommand(cCommandInput,
                inputOperation, inputFileName);

        operation = inputOperation;

        /**Function call to validate the input command******/
        commandValidateStatus = validateCommand(
                commandInterpretationStatus, inputOperation, inputFileName);

        if(commandValidateStatus==-1)
        
            printf("\n Invalid Operation");
        

        /*Exit command entered***/
        if (commandValidateStatus == 1)
        
            /*Code to clear resources */
            kill(serverPid,SIGKILL);
            kill(clientPid,SIGKILL);
            exit(0);
        
        /***Read or Delete****/
        if (commandValidateStatus == 2 || commandValidateStatus == 3)
        
            printf("\n Read or Delete\n");

            strcpy(client_MessageBuf.messageText,fileOperation);
            client_MessageBuf.messageLength=strlen(fileOperation);
            client_MessageBuf.messageType=1;
            if((writePIPE(writefd,&client_MessageBuf))<0)
            
                printf("\n Error writing on client side ");
            

            //read(readfd,*client_MessageBuf,sizeof(client_MessageBuf));
            //printf("\n Reding server responsed");
            //printf("%s",client_MessageBuf.messageText);
        
    




int main()

int pipe1[2],pipe2[2];
pipe(pipe1);
pipe(pipe2);

pid_t pid;
pid=fork();
serverPid=pid;

if(pid==0)

    /*Call Server*/
    close(pipe1[1]);
    close(pipe2[0]);
    Server(pipe1[0], pipe2[1]);   

else

    close(pipe1[0]);
    close(pipe2[1]);
    Client(pipe2[0],pipe1[1]);      

return 0;

【问题讨论】:

【参考方案1】:

看起来代码写入和读取struct msgbuf不正确:

typedef struct msgbuf 
    int messageLength;
    int messageType;
    char messageText[MSGBUFFER_SIZE];
 Message_buf;

// ...

strcpy(client_MessageBuf.messageText,fileOperation);
client_MessageBuf.messageLength=strlen(fileOperation);
client_MessageBuf.messageType=1;
if((writePIPE(writefd,&client_MessageBuf))<0)

// ....

int writePIPE(int fd, Message_buf *inputMessage)
    printf("\n In write pipe message length :%d",inputMessage->messageLength);
    printf("\n In write pipe message Data :%s",inputMessage->messageText);
    ssize_t n=write(fd,inputMessage,inputMessage->messageLength);
    printf("\n Size :%d", n);
    return n;

上面写struct msgbuf的部分只写结构的第一个messageLength字节,不包括messageLengthmessageType成员的长度,即它截断了对象。

阅读时:

ssize_t readPIPE(int fd, Message_buf *outputMessage)

    // ...
    if((n=read(fd,outputMessage,sizeof(outputMessage)))==0)

它只读取sizeof(outputMessage) 字节,这是指针的大小,而不是对象的大小。即使您通过将其更改为 sizeof(*outputMessage) 来修复它也不够,因为这会期望读取完整的对象,而写入部分会截断对象。

解决此问题的一个好的开始是将消息拆分为两部分:标头和有效负载。 header 是一个固定大小的结构,例如:

typedef struct 
    int messageType;
    int payloadLength;
 MessageHeader;

有效载荷是头部后面的可变长度部分。这样,它将首先将整个标头对象写入管道,然后是 payloadLength 字节的有效负载。读取时,它会首先再次读取整个标头,然后准确读取 payloadLength 字节。

另请注意,read()write() 调用可能读取或写入少于请求的次数,因此需要通过保持读取或写入直到处理完确切的字节数来明确处理这种情况。

【讨论】:

嗨,我确实修复了代码,并且第一次能够发送和接收数据。但是当我第二次执行它时,它给出了 SIG_PIPE 错误。你能告诉我这可能是什么原因以及如何处理这个问题 SIGPIPE 表示它写入读取器已断开连接的管道。

以上是关于从 PIPE 写入和读取结构时出错的主要内容,如果未能解决你的问题,请参考以下文章

Posix PIPE 上的非阻塞读取和阻塞写入

“无法识别的类型'员工'。忽略。C:/ .....”从.xml读取输入并将输出写入.xls文件+ perl时出错

读取和写入文件时出错(Java)[关闭]

使用 MapR MultipleOutputs 写入 OrcNewOutputFormat 时出错

为啥 bash 在写入命名管道时关闭?

将结果写入存储以供查询时出错。无法读取未定义的属性“查询”