UNIX:在进程间利用命名管道通信

    《Unix网络编程》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu10.04上测试通过。

    PS:程序里使用了包裹函数(首字母是大写的函数)和常量(所有字母都是大写的常量)的声明在my_unp.h文件中,定义在unp_base.c和unp_thread.c中,地址:http://blog.csdn.net/aaa20090987/article/details/8096701

程序简介:这个程序演示了在进程间利用命名管道通信。


服务器端:

[cpp]  view plain copy print ?
  1. #include "my_unp.h"  
  2.   
  3. #define SERV_FIFO   "/tmp/fifo.serv"  
  4.   
  5. int main(int argc, char **argv)  
  6. {  
  7.     int readfifo, writefifo, dummyfd, fd;  
  8.     char *ptr, buff[MAXLINE+1], fifoname[MAXLINE];  
  9.     pid_t pid;  
  10.     ssize_t n;  
  11.   
  12.     //创建管道文件  
  13.     if( (mkfifo(SERV_FIFO, FILE_MODE) < 0 ) &&  
  14.         (errno != EEXIST) )  
  15.         error_quit("can't create %s", SERV_FIFO);  
  16.   
  17.     //打开管道两次,一次只读,一次只写  
  18.     readfifo = Open(SERV_FIFO, O_RDONLY, 0);  
  19.     //这个描述符从来不用,但如果我们总是有一个该FIFO的描述符打开着用于写,  
  20.     //那么客户端都关闭时,服务器的read只会被阻塞,而不会返回0  
  21.     dummyfd = Open(SERV_FIFO, O_WRONLY, 0);  
  22.   
  23.     while( (n=Readline(readfifo, buff, MAXLINE)) > 0 )  
  24.     {  
  25.         //删除由Readline返回的换行符  
  26.         if'\n' == buff[n-1] )  
  27.             n--;  
  28.         buff[n] = '\0';  
  29.   
  30.         ptr = strchr(buff, ' ');  
  31.         if( NULL == ptr )  
  32.         {  
  33.             fprintf(stderr, "bogus request: %s\n", buff);  
  34.             continue;  
  35.         }  
  36.   
  37.         //根据规则得到客户端FIFO的路径  
  38.         *ptr++ = 0;  
  39.         pid = atol(buff);  
  40.         snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);  
  41.   
  42.         //打开该FIFO  
  43.         writefifo = Open(fifoname, O_WRONLY, 0);  
  44.         if( writefifo < 0 )  
  45.         {  
  46.             fprintf(stderr, "cannot open: %s\n", fifoname);  
  47.             continue;  
  48.         }  
  49.   
  50.         //打开客户端请求的文件  
  51.         fd = Open(ptr, O_RDONLY, 0);  
  52.         //若失败,则向客户端发送错误信息  
  53.         if( fd < 0 )  
  54.         {  
  55.             snprintf(buff+n, sizeof(buff)-n, ": can't open, %s\n", fifoname);  
  56.             n = strlen(ptr);  
  57.             Write(writefifo, ptr, n);  
  58.             Close(writefifo);  
  59.         }  
  60.         //若成功,则向客户端发送该文件的内容  
  61.         else  
  62.         {  
  63.             while( (n=Read(fd, buff, MAXLINE)) > 0 )  
  64.                 Write(writefifo, buff, n);  
  65.             Close(fd);  
  66.             Close(writefifo);  
  67.         }  
  68.     }  
  69.     return 0;  
  70. }  

客户端:

[cpp]  view plain copy print ?
  1. #include "my_unp.h"  
  2.   
  3. #define SERV_FIFO   "/tmp/fifo.serv"  
  4.   
  5. int main(int argc, char **argv)  
  6. {  
  7.     int readfifo, writefifo;  
  8.     size_t len;  
  9.     ssize_t n;  
  10.     char *ptr;  
  11.     char fifoname[MAXLINE], buff[MAXLINE];  
  12.     pid_t pid;  
  13.   
  14.     //指定命名管道的名称  
  15.     pid = getpid();  
  16.     snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);  
  17.   
  18.     //创建管道文件  
  19.     if( (mkfifo(fifoname, FILE_MODE) < 0 ) &&  
  20.         (errno != EEXIST) )  
  21.         error_quit("can't create %s", SERV_FIFO);  
  22.   
  23.     //用户请求由进程ID,空格,路径名和换行符组成  
  24.     snprintf(buff, sizeof(buff), "%ld ", (long)pid);  
  25.     len = strlen(buff);  
  26.     ptr = buff + len;  
  27.     Fgets(ptr, MAXLINE-len, stdin);  
  28.     len = strlen(buff);  
  29.   
  30.     //打开服务器的FIFO,并向其写入请求  
  31.     writefifo = Open(SERV_FIFO, O_WRONLY, 0);  
  32.     Write(writefifo, buff, len);  
  33.   
  34.     //从本客户的FIFO中读取服务器的应答,并写到stdin  
  35.     readfifo = Open(fifoname, O_RDONLY, 0);  
  36.     while( (n=Read(readfifo, buff, MAXLINE)) > 0 )  
  37.         Write(STDOUT_FILENO, buff, n);  
  38.   
  39.     //关闭和删除该FIFO  
  40.     Close(readfifo);  
  41.     Unlink(fifoname);  
  42.   
  43.     return 0;  
  44. }  

运行示例(红色字体的为输入)

qch@ubuntu:~/code$gcc my_unp.c temp.c -o temp
#打开一个有两行字符串的文本文件
qch@ubuntu:~/code$./temp
text.txt
I'amChinese.
Hello,world.
#打开一个我们不能读的文件
qch@ubuntu:~/code$./temp
/etc/shadow
/etc/shadow:can't open, Permission denied
#打开一个不存在的文件
qch@ubuntu:~/code$ ./temp
aaaaa
aaaaa:can't open, No such file or directory

你可能感兴趣的:(UNIX:在进程间利用命名管道通信)