2012-12-18 29 views
0

我有两个C文件,server.c和client.c。服务器必须创建一个fifo文件并不断读取它,等待输入。客户端获得其PID,并将PID写入fifo。 这是我第一次推出我的服务器上的文件:写PID先进先出 - Visual C

int main(){ 
    int fd; 
    int fd1; 
    int bytes_read; 
    char * buffer = malloc(5); 
    int nbytes = sizeof(buffer); 

    if((fd = mkfifo("serverfifo",0666)) == -1) printf("create fifo error"); 
    else printf("create fifo ok"); 

    if ((fd1 = open("serverfifo",O_RDWR)) == -1) printf("open fifo error"); 
    else{ 
     printf("open fifo ok"); 
     while(1){ 
      bytes_read = read(fd,buffer,nbytes); 
      printf("%d",bytes_read); 
      } 
     } 

return(0); 
} 

而我的客户端文件:

int main(){ 

    int fd; 
    int pid = 0; 
    char *fifo; 
    int bytes; 

    if ((pid = getpid()) == 0) printf("pid error"); 
    char pid_s[sizeof(pid)]; 
    sprintf(pid_s,"%d",pid); 


    if ((fd = open ("serverfifo",O_RDWR)) == -1)printf("open fifo error"); 
    else { 
    printf("open fifo ok"); 

     bytes = write(fd,pid_s, sizeof(pid_s)); 
     printf("bytes = %d",bytes); 

    } 

    close(fd); 
return(0); 
} 

两个我得到主要问题是:当我写的PID号的文件返回我写的字节数目看起来不错,但是当我检查fifo文件的属性时,它说0字节。第二个问题是读取不起作用。如果我在它显示之前做了一个printf,但是在它没有显示之后,并且读取没有返回任何东西,它就会冻结。 我知道有很多网站上的同类岗位的,但我无法找到任何帮助。 我正在使用Ubuntu和GCC编译器与CodeBlocks。

+1

fifos不是常规文件,它可以,如果文件报告大小为0. – yiding

+1

恐怕几乎所有代码在某种程度上都是错误的,并且在另外你的代码格式是混乱和模糊的。在继续进行客户端/服务器多进程应用程序之前,您可能需要阅读一本关于C编程的好书。 – Lundin

回答

3

有很多事情错在这里

char pid_s[sizeof(pid)]; 
sprintf(pid_s,"%d",pid); 

sizeof(pid)返回PID值的大小,而不是它的字符串表示,即,它是sizeof(int)其为4或8,取决于你的架构。然后您继续打印它。如果这样做的话,它只会运气好(你在64位机器上)。正确的做法是,如果你选择这样做,就是分配一个合适的缓冲区,并使用snprintf来确保你不会溢出。 PID的适合在5个位数,所以这样的事情会做:

char pid_s[8]; 
snprintf(pid_s, sizeof(pid_s), "%d", pid); 
当然

,你可以在服务器一起跳过这一步并发送PID的原始字节,而不是

write(fd, (void*)&pid, sizeof(pid)) 

现在你做出类似的错误:

char * buffer = malloc(5); 
int nbytes = sizeof(buffer); 

sizeof(buffer)回到4或8了,但你分配5个字节,正确的方式做到这一点,如果你想在堆上分配(用malloc),这是:

char* buffer = malloc(8); 
int nbytes = 8; 

可选地可以在栈上分配:

char buffer[8]; 
int nbytes = sizeof(buffer); 

的sizeof是排序的神奇,在,如果在阵列中传递,它返回数组的大小(8 * 1)在这种情况下。

当你阅读时,你阅读5个字节,这可能是不够的(因为你写了8个字节,由于前面的错误),所以它不会完成。你应该这样写

int pid; 
read(fd, (void*)&pid, sizeof(pid)); 

另外,如果你是真正的读写串,你会做这样的事情:

// client 
char pid_s[8]; 
snprintf(pid_s, sizeof(pid_s), "%d", pid); 
write(fd, pid_s, sizeof(pid_s)); 

// server 
char pid_s[8]; 
read(fd, pid_s, sizeof(pid_s)); 

还要注意的是读取可能会返回小于写着什么,并且您需要再次调用以继续阅读...

+0

良好的分析。在服务器中使用'O_RDWR'而不是'O_RDONLY'而在客户端使用'O_WRONLY'是个小问题;这意味着开放不会阻止。 'printf()'语句缺少换行符,因此它们不会正确跟踪流。 ''fd'被分配了'mkfifo()'的结果,然后'fd1'被分配了'open()'的结果,但读取出现在'fd'(stdin,如果'mkfifo()'成功了,错误,否则)而不是'fd1'。将'fd1'重命名为'fd',不保存'mkfifo()'的结果。关闭服务器中的文件并在退出之前取消链接()FIFO。 –

+0

感谢您的帮助,我很低级别的c编程,所以我犯了很多错误,再次感谢 – user1895293

0

那么有在这段代码有很多错误的......所有的sizeof 首先不是那样工作。 你为什么要序列化pid?

这是错误的:

char pid_s[sizeof(pid)]; 

123456是一个int,它不适合这个数组大小4的,只有3个字符可打印...

而且因为你试图序列化,你不知道预期的大小来读取PID,除非你采取最坏的情况下,写10 + 1为“\ 0” ......

+1

虽然你的陈述是准确的,并反映了海报的非常实际的问题,但似乎并没有解决这些问题将解决报告中的问题。如果是这样,你的文章应该是评论,而不是答案。 – mah