我有一个客户端服务器程序,其中客户端在PIPE上为服务器写入命令。从Server读取命令时,它只读取命令的第一个字符并抛出错误。任何人都可以帮我这个吗?
#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;
}
答案 0 :(得分:0)
看起来代码错误地写入和读取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
字节,不包括messageLength
和messageType
成员的长度,即它截断对象。
阅读时:
ssize_t readPIPE(int fd, Message_buf *outputMessage)
{
// ...
if((n=read(fd,outputMessage,sizeof(outputMessage)))==0)
它只读取sizeof(outputMessage)
个字节,这是指针的大小,而不是对象。即使您通过将其更改为sizeof(*outputMessage)
来修复它也无法做到这一点,因为它会期望读取整个对象,而写入文件会截断对象。
解决问题的良好开端是将消息拆分为两部分:标头和有效负载。标题是固定大小的结构,例如:
typedef struct {
int messageType;
int payloadLength;
} MessageHeader;
有效负载是标头后面的可变长度部分。这样,它首先将整个头对象写入管道,然后是payloadLength
字节的有效负载。在读取时,它将首先再读取整个标题,然后准确读取payloadLength
个字节。
另请注意,read()
和write()
调用的读取或写入次数可能少于询问,因此需要通过保持读取或写入来明确处理该情况,直到处理完确的字节数。