[英]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.