我在C中使用命名管道有一个客户端/服务器程序。我的服务器应该发送消息"last line"
让客户端知道最后一行即将到来,因为必须专门输出该行。我的客户在"最后一行"然后应该得到最后一行实际上是什么,但在下一个read()
之后,我的缓冲区仍然保持"最后一行"。
编辑这里要求的是我的服务器和客户端代码,其中发生了读/写操作。我的程序的总体目标是将文件名和搜索项发送到服务器,该服务器逐行读取文件并返回在每行上找到该项的频率。然后由客户打印该信息。在读完整个文件后,服务器将发送一个总计,客户端打印特殊格式。服务器结束" server-EOF"表明它已完成通信。这是一个硬件分配,所以这些是我给出的规范。
服务器:
ifstream rf(requestedFileName)
size_t found;
getline(rf,tempLine);//gets the first line of the file
while (!rf.eof())
{
currentLineNumber++;
found= tempLine.find(requestedTarget);//searches line for target
while(found != string::npos)//if it was found, increase counts and search again
{
totalTimesFoundInFile++;
totalTimesFoundOnLine++;
found=tempLine.find(requestedTarget, found+1);
}
if(totalTimesFoundOnLine != 0) //If it was found create the right string and send it to client
{
int n = sprintf(stringToSend, "Appeared on Line %d, %d times",currentLineNumber,
totalTimesFoundOnLine);
write(fd2, stringToSend, sizeof(stringToSend));
}
getline(rf,tempLine);//gets the next line
totalTimesFoundOnLine = 0; //resets the found count
}
//create the special total string.
int t = sprintf(stringToSend, "Appeared a Total of %d Times",totalTimesFoundInFile);
//Send a message to the client to let it know the special total line is coming
char finalLine[] = "final line";
if(write(fd2, finalLine, sizeof(finalLine)) != sizeof(finalLine))
{
cout<<"error writing" <<endl; }
cout <<"Just put 'finalLine' into pipe" <<endl;//lets me know the signal went out
int s= write(fd2,stringToSend, t);//writes the special total line into the pipe
if(s != t)
cout <<"error writing" <<endl;
cout <<"Just put last line into pipe" <<endl;//verifies that the special line got into the pipe and didn't block
char endingMessage[]="Server-EOF";//Let the client know the server is finished
write(fd2, endingMessage, sizeof(endingMessage));
cout <<"Wrote endingMessage" <<endl; //verifies the message got sent
客户:
char endMessage[] = "Server-EOF";
int nread;
nread = read(fd2, buffer, maxBufferSize);//reads the first input from the pipe
if(nread == -1) cout << "a read error occurred" <<endl;
else{
while(strcmp(buffer, endMessage) != 0) //check to 'server-EOF' message
{
cout << "Size of buffer is: " << strlen(buffer) <<endl;//verifies size of message recieved
if(strcmp(buffer, "final line") == 0)
{//Handler to recieve special total message and output it
nread =read(fd2, buffer, maxBufferSize);//get total message
if(nread == -1)
{
cout <<"a read error occurred" <<endl;
break;
}
else{
cout <<"Size of buffer is: " <<strlen(buffer) <<endl;//verify it got the total message
cout<< "Client : PID" << clientPID << " - Target >>"
<< requestedTarget <<"<< in File >>" << requestedFileName
<<"<< " << buffer << endl;
}
}
else{//Print out the information about search numbers for regular liens
cout <<"Client : PID " << clientPID << " - Target >>"
<<requestedTarget <<"<< " << buffer <<endl;
}
nread=read(fd2, buffer, maxBufferSize);//reads next message from pipe
if(nread == -1)
{
cout << "a read error occurred" << endl;
break;
}
}
}
输出:
Final string to send: Appeared a Total of 4 Times
Just put 'finalLine' into pipe
Just put last line into pipe
Wrote endingMessage
Size of buffer is: 27
Client : PID 5172 - Target >>apple<< Appeared on Line 1, 1 times
Size of buffer is: 27
Client : PID 5172 - Target >>apple<< Appeared on Line 2, 1 times
Size of buffer is: 27
Client : PID 5172 - Target >>apple<< Appeared on Line 4, 2 times
Size of buffer is: 10
Size of buffer is: 10
Client : PID6144 - Target >>apple<< in File >>pipedTest.txt<< final line
//This line ^^ should say something like" appeared a total of 11 times" instead of "final line"
看来我的客户正在收到消息&#34;最后一行&#34; (10个字符),但是当它应该在那之后读取总线时,它显然仍然只有&#34;最后一行&#34;在缓冲区。我知道这是因为后来的输出只是一个无限循环,最后一行&#34;作为我的缓冲区。该循环必须意味着我所有进一步的read()
调用都返回了一个带有&#34;最后一行&#34;的缓冲区。在其中
答案 0 :(得分:1)
管道是一个字节流。你不能改变它。您需要修复客户端以正确查找消息的末尾。如果您有一个字节流但需要消息流,那么您需要实现一个消息层。
这是一些破碎的代码:
nread = read(fd2, buffer, maxBufferSize);//reads the first input from the pipe
if(nread == -1) cout << "a read error occurred" <<endl;
else{
while(strcmp(buffer, endMessage) != 0) //check to 'server-EOF' message
strcmp
函数仅适用于C风格的字符串,不适用于任意数据。 nread
变量保存您读取的数据的长度,但您完全忽略它来处理数据。这不可行。
答案 1 :(得分:0)
保证数据有序,但即使是短消息也可能以块的形式到达。您可以尝试关闭管道,然后打开一个新管道,如果您想要它新鲜。或者您可以添加某种终止以指示每次传输的结束。接收信息的代码必须将传入数据添加到缓冲区,然后才能找到结束(这可以指示下一条消息的开始)。