簡體   English   中英

文件傳輸成功,但在 C 中循環時不會退出

[英]File transfer successful but won't exit while loop in C

編輯:將 while 循環條件從> 0更改為!=0 打印內容后,終端上還會輸出 2 個或更多換行符,但文件中沒有。

我正在將文件從客戶端傳輸到服務器。 內容傳輸成功,但接收時不退出while循環。 我的 while 條件有什么問題嗎? 強制停止程序后,我可以看到文件實際上已成功復制,只是在將所有內容寫入文件后並沒有退出此 while 循環。

這是我遇到問題的代碼:

ssize_t bytes_read = 0;
int error;

while((bytes_read = read(sd, buf, sizeof(buf))) != 0){ 
                        
                        printf("writing: %s\n", buf);
                        if((error = fwrite(buf, 1, bytes_read, fp)) < 0)
                        {
                            printf("error");
                        }
                        if((bytes_read = read(sd, buf, sizeof(buf))) < 0){
                            break;
                        }
                            
}

盡量保持最小,因為我確信這里有一些非常簡單的錯誤。

編輯:我用一個更大的文件嘗試了它,它似乎在這里和那里缺少一些內容,但不是一致的模式。

編輯:這是客戶端。

else if(strcmp(shortCommand, "put") == 0){
            
            char *tmp = buf + 4;
            char filename[MAX_BLOCK_SIZE];
            strcpy(filename, "filename ");
            strcat(filename, tmp);
            FILE *fp;
            printf("File name: %s\n", tmp);
            fp = fopen(tmp, "rb");
            if(fp == NULL){
                
                printf("ERROR: Requested file does not exist.\n");
                
            }
            else{
            printf("Client sending filename...\n");
            if ((nw = write(sd, buf, sizeof(buf))) < 0){            //sending the file name to the client first
                printf("Error sending client's filename.\n");
            }
            
            printf("Client sending file...\n");
            size_t bytes_read = 0;
            ssize_t bytes_written = 0;
            
            
            while((bytes_read = fread(buf, 1, sizeof(buf), fp)) != 0){ //sending the file contents
            
                if ((bytes_written = write(sd, buf, bytes_read)) < 0){
                    printf("Error sending client file.\n");
                }
            
            }
            
            fclose(fp);
            }   
    }

服務器代碼假定它會在讀取客戶端傳輸的所有數據后觀察到read()返回 0,但這不會僅僅因為客戶端停止發送數據而發生。 read()返回 0 表示已到達文件末尾,但“文件”在這種意義上意味着其套接字的讀取端。 在客戶端關閉對等套接字之前,服務器不會在其套接字上感知 EOF。 這是完全合理的,因為在那之前,客戶端可能會發送更多數據,證明之前確實沒有達到 EOF。 因此,如果服務器在接收到所有數據后嘗試對套接字執行(阻塞)讀取,那么它將阻塞直到客戶端發送更多或關閉連接,或者直到它檢測到錯誤,被信號中斷。 .

如果客戶端實際上並不打算在文件內容之后發送任何進一步的數據,那么它應該在發送文件內容的所有字節后close()該套接字,或者至少shutdown()寫入端。

另一方面,如果客戶端因為打算稍后發送更多數據而保持套接字打開,那么您需要一個新策略。 在這種情況下,文件內容的結尾與流的邏輯結尾不一致,因此您需要一種不同的機制來與文件數據結尾所在的服務器進行通信。 這就是 HTTP 等通信協議的用武之地,但就您的目的而言,您不需要像 HTTP 一樣復雜的協議。

例如,客戶端將數據作為一個或多個塊發送到服務器可能就足夠了,每個塊包含一個字節計數,后跟指定數量的內容字節。 您可以堅持將整個文件內容始終放在一個塊中,但是如果您想允許將文件拆分為多個塊,那么您可以使用塊長度為零來表示數據結束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM