簡體   English   中英

讀取卡住的套接字上的系統調用[C語言]-無法通過套接字發送二進制文件

[英]read system call on socket stuck [C language] - failed to send binary file over socket

我有客戶端服務器體系結構,其中我將二進制文件從服務器傳輸到客戶端。

服務器代碼:

            FILE *outFile = fopen("/tmp/localpkg.deb","wb");
            if( outFile == NULL )
            {
                     RPTLOG(1, "Error opening file for writing.\n");
                     return -1;
            }

            FILE *readFilefp = fopen(file_name, "rb");

            if ( readFilefp == NULL)
            {
                     RPTLOG(1, "Error opening file.\n");
                     return -1;
            }

            char fileBuffer[1024];
            bzero(fileBuffer, 1024);

            while(1)
            {

                    size_t readSize = fread(fileBuffer, sizeof(char), sizeof(fileBuffer) -1, readFilefp);

                    if(readSize == 0)
                    {
                            RPTLOG(1, "No more contents are left in file.\n");
                            n = write(sockfd, "\r\n", 2);
                            break;
                    }

                    n = write(sockfd, fileBuffer,readSize);

                    fwrite(&fileBuffer, sizeof(char), readSize, outFile);

                    RPTLOG(1, "Data[%d] written to sock=%s.\n", n, fileBuffer);
                    bzero(fileBuffer, 1024);

            }

            fclose(readFilefp);
            fclose(outFile);

            char *endfile_var =(char*) malloc(2048);
            bzero(endfile_var,100);
            strcpy(endfile_var,"ENDFILE\r\n");

            n = write(sockfd, endfile_var, 9 );

            RPTLOG(1, "ENDFILE text sent to client[%s] NumBytes sent=%d\n", endfile_var, n );

客戶代碼:

                   FILE *fp = fopen(localfile, "wb");
                    if( fp == NULL )
                    {
                            RPTLOG(1, "Not enough permissions to write on disk, exiting....\n");
                            break;
                    }

                    memset(buf, 0, 2048);

                    //Started receiving installation package from server
                    while ((ret = read(sock, buf, 2047)) > 0) //Stcuk point: read blocks over here when it is about to receive last few lines of
                    {                                         //binary file from server

                            buf[ret] = '\0';

                            if ( ret == 1 )
                            {
                                    RPTLOG(1, "Caught character  where ret = %d\n", ret);
                                    if ( buf[0] == '\n' )
                                            continue;
                            }

                            if (strstr(buf, "ENDFILE") != 0 )
                            {
                                    RPTLOG(1, "Endfile detected\n");
                                    break;
                            }
                            else
                            {
                                    fwrite(buf, 1, ret, fp);
                            }

                            memset(buf, 0, 2048);

                    }

                    if( ret ==  0)
                    {
                            RPTLOG(4, "Connection closed from server = %d \n", ret );
                    }
                    else if( ret <  0)
                    {
                            RPTLOG(4, "Read error on client socket= %d \n", ret );
                    }

                    fclose(fp);

我的問題 :當服務器要發送最后幾行二進制文件時,客戶端卡在讀取調用中[ 上面發布的客戶端代碼中的卡點 ]。 在這里,客戶端程序的設計方式是,當它從服務器接收到“ ENDFILE”行時,它將假定文件內容已從服務器端結束並退出while循環。

因此,建議您從服務器成功接收二進制文件的解決方案。

[ 特別注意 :]客戶端代碼已包裝在內部版本中,並已在客戶端安裝。 因此,我只需要更改服務器端代碼。 同樣如上面的服務器代碼所示,出於調試目的,我還將通過套接字發送的內容寫入了“ /tmp/localpkg.deb”文件。 該文件包含所有寫在服務器端套接字上的內容。

[特別注意2:]當我嘗試發送純文本文件時,可以成功發送它。 問題僅在發送二進制文件時出現。 提前致謝。

代碼失敗的原因很簡單。 您正在將大量二進制數據讀取到buf中,然后在此buf上調用strstr 查找給定令牌時, strstr會一直到第一個\\0字節。 顯然,二進制數據將包含大量數據,因此搜索將在遇到第一個數據后停止並返回“未找到任何內容”。

結果,您的代碼永遠不會退出讀取循環,並一直在等待更多數據從服務器到達-永遠不會發送。

當然,正確的解決方案是實現用於發送二進制數據的正確協議。 但是,如果由於列出的限制而無法實現,則一種可行的解決方案是用自定義函數替換strstr函數,該函數將忽略忽略的nul終止符而使用提供的緩沖區(改為使用緩沖區的大小),查找提供的令牌。 如果您的二進制數據中包含令牌,它仍然會中斷,但是您無能為力。

暫無
暫無

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

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