读书人

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

发布时间: 2013-01-23 10:44:50 作者: rapoo

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

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

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

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


服务器端:

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

客户端:

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

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

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

读书人网 >UNIXLINUX

热点推荐