Chinaunix首页 | 论坛 | 博客
  • 博客访问: 90787
  • 博文数量: 19
  • 博客积分: 442
  • 博客等级: 下士
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-11 15:31
文章分类
文章存档

2011年(19)

分类: C/C++

2011-08-17 12:00:01

从网上看到一个例子,就是利用命名管道通信,分为读写端。

现在的问题是,当我启动读这一段,他就循环着去读取管道中的内容,
而当我运行写端的话,只能够执行一次,第二次就出错
[open: No such device or address]


我就想知道为什么,我的环境是cygwin!

代码如下

server.c
-----------------------------------------------------------------------------------------------
/*
* 管道通信:有名管道
* 无名管道只能用于具有亲缘关系的进程之间,而有名管道可以在互不相关的两个进程间
* 实现彼此通信。要注意,FIFO严格按照先进先出的规则,对管道及FIFO的读总是从开始
* 处返回数据,对它们的写则把数据添加到末尾,不支持lseek等文件定位操作。
*
* 有名管道的创建使用mkfifo()。创建成功后就可以使用open、read、write这些函数了。
* 读管道部分
*/

#include
#include
#include
#include
#include
#include
#include
#include

/*在这里设置打开管道文件的mode为只读形式*/
#define FIFOMODE (O_CREAT | O_RDWR | O_NONBLOCK)
#define OPENMODE (O_RDONLY | O_NONBLOCK)
#define FIFO_SERVER "myfifo"

int main(void)
{
        char buf[100];
        int fd;
        int readnum;

        /*创建有名管道,设置为可读写,无阻塞,如果不存在则按照指定权限创建*/
        if ((mkfifo(FIFO_SERVER, FIFOMODE) < 0) && (errno != EEXIST)) {
                printf("cannot create fifoserver\n");
                exit(1);
        }

        printf("Preparing for reading bytes... ...\n");

        /*打开有名管道,并设置非阻塞标志*/
        if ((fd = open(FIFO_SERVER, OPENMODE)) < 0) {
                perror("open");
                exit(1);
        }

        while (1) {
                /*初始化缓冲区*/
                bzero(buf, sizeof(buf));
                /*读取管道数据*/
                if ((readnum = read(fd, buf, sizeof(buf))) < 0) {
                        if (errno == EAGAIN) {
                                printf("no data yet\n");
                        }
                }
                /*如果读到数据则打印出来,如果没有数据,则忽略*/
                if (readnum > 0) {
                        buf[readnum] = '\0';
                        printf("read %s from FIFO_SERVER\n", buf);
                }
                sleep(3);
        }

        return 0;
}
---------------------------------------------------------------------------------------------------------

client.c
---------------------------------------------------------------------------------------------------------
/*
* 管道通信:有名管道
* 无名管道只能用于具有亲缘关系的进程之间,而有名管道可以在互不相关的两个进程间
* 实现彼此通信。要注意,FIFO严格按照先进先出的规则,对管道及FIFO的读总是从开始
* 处返回数据,对它们的写则把数据添加到末尾,不支持lseek等文件定位操作。
*
* 有名管道的创建使用mkfifo()。创建成功后就可以使用open、read、write这些函数了。
* 写管道部分
*/

#include
#include
#include
#include
#include
#include
#include
#include

/*特别注意写管道时,设置打开管道文件的格式必须为可写*/
#define FIFOMODE (O_CREAT | O_RDWR | O_NONBLOCK)
#define FIFO_SERVER "myfifo"
#define OPENMODE (O_WRONLY | O_NONBLOCK)

int main(int argc, char **argv)
{
        int fd;
        int nwrite;

                /*创建有名管道,设置为可读写,无阻塞,如果不存在则按照指定权限创建*/
       /* if ((mkfifo(FIFO_SERVER, FIFOMODE) < 0) && (errno != EEXIST)) {
                printf("cannot create fifoserver\n");
                //exit(1);
        }*/

        /*打开管道文件,可写非阻塞*/
        if ((fd = open(FIFO_SERVER, OPENMODE,0)) < 0) {
                perror("open");
                                if(errno == ENXIO){
                                        perror("errrr");
                                }
                exit(1);
        }

        /*如果没有在命令行中写入参数,那么要重新运行程序*/
        if (argc == 1) {
                printf("Please send something\n");
                exit(1);
        }

        /*向管道文件中写入数据,在这里要用strlen,如果用sizeof,则只是4个字节的指针长度*/
        if ((nwrite = write(fd, argv[1], strlen(argv[1]))) < 0) {
                if (errno == EAGAIN) {
                        printf("The FIFO has not been read yet.Please try later\n");
                }
        }
        else {
                printf("write %s to FIFO\n", argv[1]);
        }
                //close(fd);
        return 0;
}
---------------------------------------------------------------------------------------------------------



求解答。

(找他人在linux环境下好像就没有问题,client端可以写多次)

| | |

客户端 每启动一次就写一次 你close(fd) 注释了   管道只能打开一端
你多次运行 没有closed(fd) 多次打开写端 肯定不行  你都没关闭的

| | |



QUOTE:
客户端 每启动一次就写一次 你close(fd) 注释了   管道只能打开一端
你多次运行 没有closed(fd) 多次打开写 ...
Fatihyang 发表于 2011-08-11 09:55




    您的意思是我要在client里面加上close(fd)么?

这样也是不行的~~

| | |

回复 3# nideai03


    这个就不知道了
不了解你的环境

| | |

回复 1# nideai03


    建议楼主装个虚拟机    cygwin毕竟不是 正真的linux    又不大

| | |

函数说明
mkfifo() 会依参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限(mode%~umask),因此 umask值也会影响到FIFO文件的权限。Mkfifo()建立的FIFO文件其他进程都可以用读写一般文件的方式存取。当使用open()来打开 FIFO文件时,O_NONBLOCK旗标会有影响
1、当使用O_NONBLOCK 旗标时,打开FIFO 文件来读取的操作会立刻返回,但是若还没有其他进程打开FIFO 文件来读取,则写入的操作会返回ENXIO 错误代码。
2、没有使用O_NONBLOCK 旗标时,打开FIFO 来读取的操作会等到其他进程打开FIFO文件来写入才正常返回。同样地,打开FIFO文件来写入的操作会等到其他进程打开FIFO 文件来读取后才正常返回。
返回值
若成功则返回0,否则返回-1,错误原因存于errno中。

| | |

本机测试是可以的。
client中屏蔽的地方应该打开。
1、前面的mkfifo有exist的判断,不会有影响。可打开。
2、close就更该打开了。

楼主的报错是ENXIO,如果关闭server(读端),再打开client(写端),由于没人读,就会报这个错误。
阅读(1438) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~