2012-12-18 45 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