套接字上的读取系统调用卡住[C语言]-无法通过套接字发送二进制文件

套接字上的读取系统调用卡住[C语言]-无法通过套接字发送二进制文件,c,linux,sockets,socket.io,raw-sockets,C,Linux,Sockets,Socket.io,Raw Sockets,我有一个客户机-服务器体系结构,其中我将二进制文件从服务器传输到客户机 服务器代码: FILE *outFile = fopen("/tmp/localpkg.deb","wb"); if( outFile == NULL ) { RPTLOG(1, "Error opening file for writing.\n"); return -

我有一个客户机-服务器体系结构,其中我将二进制文件从服务器传输到客户机

服务器代码:

            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);
客户端代码:

            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);
FILE*fp=fopen(localfile,“wb”);
如果(fp==NULL)
{
RPTLOG(1,“没有足够的权限在磁盘上写入,正在退出…”\n);
打破
}
memset(buf,02048);
//已开始从服务器接收安装包
while((ret=read(sock,buf,2047))>0)//Stcuk point:当它即将接收最后几行数据时,读取这里的块
{//来自服务器的二进制文件
buf[ret]='\0';
如果(ret==1)
{
RPTLOG(1,“捕获的字符,其中ret=%d\n”,ret);
如果(buf[0]='\n')
继续;
}
如果(strstr(buf,“ENDFILE”)!=0)
{
RPTLOG(1,“检测到Endfile\n”);
打破
}
其他的
{
fwrite(buf,1,ret,fp);
}
memset(buf,02048);
}
如果(ret==0)
{
RPTLOG(4,“从服务器关闭的连接=%d\n”,ret);
}
否则如果(ret<0)
{
RPTLOG(4,“客户端套接字上的读取错误=%d\n”,ret);
}
fclose(fp);
我的问题: 当服务器即将发送最后几行二进制文件时,客户端卡在读取调用中[上面张贴的客户端代码中的卡点]。在这里,客户机程序的设计方式是,当它从服务器接收到“ENDFILE”行时,它将假定文件内容已经从服务器端结束,并从while循环中出来

因此,请建议成功从服务器接收二进制文件的解决方案

[特别注意:]客户端代码已打包在一个构建中,并安装在客户端。因此,我只需要在服务器端代码中进行更改。同样如上面的服务器代码所示,出于调试目的,我还将套接字上的内容写入了“/tmp/localpkg.deb”文件。该文件包含服务器端套接字上写入的所有内容

[特别说明2::当我尝试发送纯文本文件时,我可以成功发送它。只有在发送二进制文件时才会出现问题。
提前感谢。

代码失败的原因很简单。您正在将一大块二进制数据读入buf,然后在此buf上调用
strstr
strstr
在查找给定令牌时一直到第一个
\0
字节。显然,二进制数据中会有很多这样的内容,所以搜索在遇到第一个之后停止,并返回“nothing was found”

因此,您的代码永远不会退出读取循环,并一直等待更多数据从服务器到达,而服务器永远不会发送数据


当然,正确的解决方案是实现发送二进制数据的正确协议。但是,如果由于列出的约束条件,这是不可能的,一个半可行的解决方案是用自定义函数替换
strstrstr
函数,该函数将忽略nul终止符(改为使用缓冲区的大小)并查找提供的令牌。如果二进制数据中有令牌,它仍然会中断,但您对此无能为力。

检查服务器发送的字节数,然后将其与客户端接收的字节数进行比较。如果没有更多的数据从套接字读取,客户端将继续等待。如果链接必须使用ascii码处理二进制数据检查,那么设计非常糟糕,毫无意义。二进制文件可以包含任何内容,甚至可以包含空字节。如果在
ENDFILE
代码之前有一个,则传输结束检查将始终失败!货物崇拜“memset(buf,0,2048);”buf[ret]='\0';'这两个函数对二进制传输都没有用:(@MartinJames,第二个OP必须这样做——因为OP调用的是
strstr
。真正的货物在这里:
char*endfile\u var=(char*)malloc(2048);bzero(endfile\u var,100);strcpy(endfile\u var,“endfile\r\n”);
:)@SergeyA哦,我相信你。我没有看服务器代码,我肯定这也有‘问题’:(哈哈,就从标题来看,肯定是误用str*调用:)