UNIX:在过程间利用命名管道通信
UNIX:在进程间利用命名管道通信
客户端:
qch@ubuntu:~/code$gcc my_unp.c temp.c -o temp
《Unix网络编程》这本书附带了许多短小精美的小程序,我在阅读此书的时候,将书上的代码按照自己的理解重写了一遍(大部分是抄书上的),加深一下自己的理解(纯看书太困了,呵呵)。此例子在Ubuntu10.04上测试通过。
PS:程序里使用了包裹函数(首字母是大写的函数)和常量(所有字母都是大写的常量)的声明在my_unp.h文件中,定义在unp_base.c和unp_thread.c中,地址:http://blog.****.net/aaa20090987/article/details/8096701
程序简介:这个程序演示了在进程间利用命名管道通信。
服务器端:
- #include "my_unp.h"
- #define SERV_FIFO "/tmp/fifo.serv"
- int main(int argc, char **argv)
- {
- int readfifo, writefifo, dummyfd, fd;
- char *ptr, buff[MAXLINE+1], fifoname[MAXLINE];
- pid_t pid;
- ssize_t n;
- //创建管道文件
- if( (mkfifo(SERV_FIFO, FILE_MODE) < 0 ) &&
- (errno != EEXIST) )
- error_quit("can't create %s", SERV_FIFO);
- //打开管道两次,一次只读,一次只写
- readfifo = Open(SERV_FIFO, O_RDONLY, 0);
- //这个描述符从来不用,但如果我们总是有一个该FIFO的描述符打开着用于写,
- //那么客户端都关闭时,服务器的read只会被阻塞,而不会返回0
- dummyfd = Open(SERV_FIFO, O_WRONLY, 0);
- while( (n=Readline(readfifo, buff, MAXLINE)) > 0 )
- {
- //删除由Readline返回的换行符
- if( '\n' == buff[n-1] )
- n--;
- buff[n] = '\0';
- ptr = strchr(buff, ' ');
- if( NULL == ptr )
- {
- fprintf(stderr, "bogus request: %s\n", buff);
- continue;
- }
- //根据规则得到客户端FIFO的路径
- *ptr++ = 0;
- pid = atol(buff);
- snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);
- //打开该FIFO
- writefifo = Open(fifoname, O_WRONLY, 0);
- if( writefifo < 0 )
- {
- fprintf(stderr, "cannot open: %s\n", fifoname);
- continue;
- }
- //打开客户端请求的文件
- fd = Open(ptr, O_RDONLY, 0);
- //若失败,则向客户端发送错误信息
- if( fd < 0 )
- {
- snprintf(buff+n, sizeof(buff)-n, ": can't open, %s\n", fifoname);
- n = strlen(ptr);
- Write(writefifo, ptr, n);
- Close(writefifo);
- }
- //若成功,则向客户端发送该文件的内容
- else
- {
- while( (n=Read(fd, buff, MAXLINE)) > 0 )
- Write(writefifo, buff, n);
- Close(fd);
- Close(writefifo);
- }
- }
- return 0;
- }
客户端:
- #include "my_unp.h"
- #define SERV_FIFO "/tmp/fifo.serv"
- int main(int argc, char **argv)
- {
- int readfifo, writefifo;
- size_t len;
- ssize_t n;
- char *ptr;
- char fifoname[MAXLINE], buff[MAXLINE];
- pid_t pid;
- //指定命名管道的名称
- pid = getpid();
- snprintf(fifoname, sizeof(fifoname), "/tmp/fifo.%ld", (long)pid);
- //创建管道文件
- if( (mkfifo(fifoname, FILE_MODE) < 0 ) &&
- (errno != EEXIST) )
- error_quit("can't create %s", SERV_FIFO);
- //用户请求由进程ID,空格,路径名和换行符组成
- snprintf(buff, sizeof(buff), "%ld ", (long)pid);
- len = strlen(buff);
- ptr = buff + len;
- Fgets(ptr, MAXLINE-len, stdin);
- len = strlen(buff);
- //打开服务器的FIFO,并向其写入请求
- writefifo = Open(SERV_FIFO, O_WRONLY, 0);
- Write(writefifo, buff, len);
- //从本客户的FIFO中读取服务器的应答,并写到stdin
- readfifo = Open(fifoname, O_RDONLY, 0);
- while( (n=Read(readfifo, buff, MAXLINE)) > 0 )
- Write(STDOUT_FILENO, buff, n);
- //关闭和删除该FIFO
- Close(readfifo);
- Unlink(fifoname);
- return 0;
- }
运行示例(红色字体的为输入)