我正在创建一个非常简单的程序,它由客户端使用的小API和服务器进程组成。客户端进程和服务器进程通过一对FIFO进行通信(一个用于对服务器的请求,另一个用于来自服务器的响应)。
最后一次写入似乎没有阻止服务器进程,直到客户端在另一端读取:为什么?我错过了什么? 为了实现我的目标,我必须在写入调用之前放置一个sleep(1),但这仅适用于对服务器的某种请求:我如何帮助您帮助我?
服务器代码
/* until here everything is ok: client read the response and waits for the buffer */
sleep(1);
/* open the FIFO and send the buffer */
if((fifofrom = open(FIFOFROMMMBOXD, O_WRONLY)) == -1) logMmboxd("error in opening FIFOFROM again for the buffer\n", 1);
else logMmboxd("opened FIFOFROM again for the buffer\n", 0);
if((write(fifofrom, mails, sizeof(mmbox_mail_complete)*m)) != sizeof(mmbox_mail_complete)*m) logMmboxd("error in writing FIFOFROM again for the buffer\n", 1);
else logMmboxd("written on FIFOFROM again for the buffer\n", 0);
close(fifofrom);
logMmboxd("messages list definitely sent\n", 0);
客户代码
void lockUp(Request *request, Response *response, void **buffer)
{
int fifofrom, fifoto, lock;
/* lockto access the FIFOs */
if((lock = open(LOCK, O_RDONLY)) == -1) logMmboxman("error in opening LOCK\n", 1);
else logMmboxman("opened LOCK\n", 0);
if(flock(lock, LOCK_EX) == -1) logMmboxman("error in acquiring LOCK\n", 1);
else logMmboxman("acquired LOCK\n", 0);
/* open the FIFO and write the request */
if((fifoto = open(FIFOTOMMBOXD, O_WRONLY)) == -1) logMmboxman("error in opening FIFOTO\n", 1);
else logMmboxman("opened FIFOTO\n", 0);
if((write(fifoto, request, sizeof(Request))) != sizeof(Request)) logMmboxman("error in writing FIFOTO\n", 1);
else logMmboxman("written on FIFOTO\n", 0);
close(fifoto);
/* waiting for response on FIFOFROM */
if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1) logMmboxman("error in opening FIFOFROM\n", 1);
else logMmboxman("opened FIFOFROM\n", 0);
if((read(fifofrom, response, sizeof(Response))) != sizeof(Response)) logMmboxman("error in reading FIFOFROM\n", 1);
else logMmboxman("read from FIFOFROM\n", 0);
close(fifofrom);
/* if size>0 then the server has to send a buffer of data to me! */
if(response->size)
{
if((fifofrom = open(FIFOFROMMMBOXD, O_RDONLY)) == -1) logMmboxman("error in opening FIFOFROM again for the buffer\n", 1);
else logMmboxman("opened FIFOFROM again for the buffer\n", 0);
*buffer = (void*)malloc(response->size);
if(read(fifofrom, *buffer, response->size) != response->size) logMmboxman("error in reading FIFOFROM again for the buffer\n", 1);
else logMmboxman("read from FIFOFROM again for the buffer\n", 0);
close(fifofrom);
}
/* read the response: I release the lock */
if(flock(lock, LOCK_UN) == -1) logMmboxman("error in releasing LOCK\n", 1);
else logMmboxman("released LOCK\n", 0);
return;
}
答案 0 :(得分:0)
所以(1)关于FIFO同步的理由是正确的; (2)linux几乎没有机会搞砸了;所以(3)你有一个错误。
很难说但是因为你最初打开服务器fifo作为O_RDWR,也许你没有关闭你的想法?也许你有第二个运行的客户端已经将fifo作为读者打开,当你以O_WRONLY重新打开时它不会阻塞?
无论如何,您真正的问题是您设计的协议。你不需要我可以看到需要锁或保持打开和关闭fifos。你需要一个明智的沟通协议。
通常情况如下:
(1)服务器有一个众所周知的fifo客户端打开并写入。
(2)客户传递交易代码或表明这是初始请求的事情。包括服务器建立连接回客户端的一些方法。这可能是一个完整的路径名,或者只是一个客户端和服务器使用预定的路径创建第二个fifo的pid(例如,打开“/ tmp / myfifo_pid”或其他一些)。
(3)客户&服务器打开第二个fifo,对服务器的所有进一步客户端请求包括pid(或其他),以便服务器知道输出请求的位置。
(4)完成所有操作后,客户端发送一个指示这样的事务,以便服务器可以关闭第二个fifo。客户也这样做。
(5)重复许多客户。
请注意,您需要指定邮件的格式。历史悠久的技术是使用长度代码(似乎是你正在尝试的)或某种msg结束分隔符(例如换行符)。
修改强>
可能的邮件格式:
长度| TRANCODE ||数据|
其中length表示整个消息包含多少个后续字节,转码指定和操作(例如打开我的输出fifo,关闭它,发送数据等等),数据是适合该事务的任何内容。