C++ Linux服务器,将文件发送到windows客户端(套接字)

C++ Linux服务器,将文件发送到windows客户端(套接字),c++,c,linux,sockets,C++,C,Linux,Sockets,当我将文件发送到客户端时,它会被损坏,并且大小(以字节为单位)更大。 我有一个版本的服务器运行在Windows上,工作非常完美,但在Linux上没有相同的结果 磁盘上的文件大小可能是将以字节为单位的大小发送到另一个平台上运行的客户端的时间错误 客户端工作得很好,正如我所说,我有一个在Windows上运行的服务器版本,唯一的区别是fread:Size=fread(mfcc,1,min(sizeof(mfcc),FileSize),fp) fread功能是否正确使用? 专家能分析并帮助发现错误吗 i

当我将文件发送到客户端时,它会被损坏,并且大小(以字节为单位)更大。

我有一个版本的服务器运行在Windows上,工作非常完美,但在Linux上没有相同的结果

磁盘上的文件大小可能是将以字节为单位的大小发送到另一个平台上运行的客户端的时间错误

客户端工作得很好,正如我所说,我有一个在Windows上运行的服务器版本,唯一的区别是fread:
Size=fread(mfcc,1,min(sizeof(mfcc),FileSize),fp)

fread功能是否正确使用?

专家能分析并帮助发现错误吗

int Socket_Setup::FILE_UPLOAD(int iD, std::string DIR_UPLOAD)
{   
    char Block[1024]; 
    long FileSize;      
    fp = fopen(DIR_UPLOAD.c_str(), "rb");
    if (!fp)
    {
          errno_message.append((char*)strerror(errno));
          FUNCTION_LOG(errno_message);
          return 1;
    }

    fseek(fp, 0, SEEK_END);
    FileSize = ftell(fp);
    rewind(fp);

    long Size_Send = htonl(FileSize);
    Total = FileSize;

    // Sending the file size to the Windows Client  
    iResult = send(client[iD].socket, (const char*)&Size_Send, sizeof(long), 0);        
    if (iResult <= 0)
    {
          errno_message.append((char*)strerror(errno));
          FUNCTION_LOG(errno_message);
          return 1;
    }   

     while (FileSize > 0)
    {
        BytesRead = fread(Block, 1, sizeof(Block), fp);
        if (BytesRead <= 0)
        {
            errno_message.append((char*)strerror(errno));
            FUNCTION_LOG(errno_message);
            fclose(fp);
            return 1;
        }
        if (send(client[iD].socket, Block, BytesRead, 0) != BytesRead)
        {
            errno_message.append((char*)strerror(errno));
            FUNCTION_LOG(errno_message);
            fclose(fp);
            return 1;
        }
        FileSize -= BytesRead;      
    }
    fclose(fp);
    return 0;
}
int-Socket\u设置::文件上传(int-iD,std::字符串目录上传)
{   
字符块[1024];
长文件大小;
fp=fopen(DIR_UPLOAD.c_str(),“rb”);
如果(!fp)
{
errno_message.append((char*)strerror(errno));
功能日志(错误信息);
返回1;
}
fseek(fp,0,SEEK_END);
FileSize=ftell(fp);
倒带(fp);
长大小_Send=htonl(文件大小);
总数=文件大小;
//将文件大小发送到Windows客户端
iResult=send(客户端[iD].socket,(常量字符*)&Size\u send,sizeof(长),0);
如果(iResult 0)
{
BytesRead=fread(块,1,sizeof(块),fp);

如果(BytesRead我认为你的问题在这里:

iResult = send(client[iD].socket, (const char*)&Size_Send, Size_Send, 0);       
您正在通过此调用发送Size_Send字节(其中大多数是Size_Send变量结束后的杂项内存),而不是您可能想要发送sizeof(长)字节的内容。请将上行中发送的Size_的第二个实例替换为sizeof(长)并且您将获得更好的结果。

假设使用了

分析

让我们考虑下面的代码:

  • 正在发送文件大小

    // Sending the file size to the Windows Client  
    iResult = send(client[iD].socket, (const char*)&Size_Send, sizeof(long), 0);
    if (iResult <= 0)
    {
          errno_message.append((char*)strerror(errno));
          FUNCTION_LOG(errno_message);
          return 1;
    }
    
  • send()
    函数不能保证“一次”发送所有数据(即通过单个函数调用):

    返回值 成功完成后,
    send()
    应返回发送的字节数。否则,应返回-1,并设置
    errno
    以指示错误

    -

    因此,
    if(send(client[iD].socket,Block,BytesRead,0)!=BytesRead)
    检查似乎不正确

    解决方案 必须使用
    send()
    函数的返回值来实现循环,以发送先前由
    fread()
    函数调用读取的所有字节。 请参阅
    SendAllBytes()
    函数的实现。它应该用于更正这两段代码(请参阅“分析”部分)

    以下代码仅作为示例:

    #include <stdio.h>
    #include <sys/socket.h>
    
    ...
    
    if (SendAllBytes(socket, &file_size, sizeof(file_size)) != 0) {
        // Error.
        return;
    }
    
    ...
    
    char buffer[1024];
    while (feof(file_stream) == 0) {
        const size_t bytes_read = fread(buffer, sizeof(*buffer), sizeof(buffer) / sizeof(*buffer), file_stream);
        // Upon successful completion, fread() shall return the number of elements
        // successfully read which is less than nitems only if a read error or end-of-file is encountered.
        // If size or nitems is 0, fread() shall return 0 and the contents of the array and the state of the stream remain unchanged.
        // Otherwise, if a read error occurs, the error indicator for the stream shall be set, and errno shall be set to indicate the error.
        // (Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fread.html).
        if (bytes_read < sizeof(buffer) / sizeof(*buffer) &&
            ferror(file_stream) != 0) {
            // Error.
            return;
        }
    
        if (SendAllBytes(socket, buffer, bytes_read) != 0) {
            // Error.
            return;
        }
    }
    
    int SendAllBytes(int socket, const char *buffer, size_t bytes_to_send)
    {
        size_t total_bytes_sent = 0;
        while (bytes_to_send > 0) {
            const ssize_t bytes_sent = send(socket, &buffer[total_bytes_sent], bytes_to_send, 0);
            // Upon successful completion, send() shall return the number of bytes sent.
            // Otherwise, -1 shall be returned and errno set to indicate the error.
            // (Source: http://pubs.opengroup.org/onlinepubs/9699919799/).
            if (bytes_sent == -1) {
                // Error.
                return -1;
            }
    
            total_bytes_sent += bytes_sent;
            bytes_to_send -= bytes_sent;
        }
        return 0;
    }
    
    #包括
    #包括
    ...
    if(SendAllBytes(套接字,&文件大小,sizeof(文件大小))!=0){
    //错误。
    返回;
    }
    ...
    字符缓冲区[1024];
    while(feof(文件流)==0){
    const size\u t bytes\u read=fread(buffer,sizeof(*buffer),sizeof(buffer)/sizeof(*buffer),文件流);
    //成功完成后,fread()将返回元素数
    //仅当遇到读取错误或文件结束时,才成功读取小于nitems的数据。
    //如果size或nitems为0,则fread()将返回0,并且数组的内容和流的状态保持不变。
    //否则,如果发生读取错误,则应设置流的错误指示器,并设置errno以指示错误。
    //(来源:http://pubs.opengroup.org/onlinepubs/9699919799/functions/fread.html).
    if(字节读取0){
    const ssize_t bytes_sent=send(套接字和缓冲区[total_bytes_sent],bytes_to_send,0);
    //成功完成后,send()将返回发送的字节数。
    //否则,应返回-1,并设置errno以指示错误。
    //(来源:http://pubs.opengroup.org/onlinepubs/9699919799/).
    如果(发送的字节数==-1){
    //错误。
    返回-1;
    }
    发送的总字节数+=发送的字节数;
    字节发送-=字节发送;
    }
    返回0;
    }
    
    携带说明
    考虑使用增强可移植性。在上述情况下,文件大小不是由固定宽度整数类型表示的。

    现在,以字节为单位的大小几乎相等,但仍然会损坏文件。没错,我不太了解fread函数如何工作,我该怎么做?损坏的性质是什么?文件没有打开时,我试图发送一个jpg,但该文件没有显示,它还附带了来自服务器的文件的大部分字节。您是否尝试运行WireShark以查看哪些字节实际通过该线路?如果通过该线路的字节与文件中的字节相匹配,则表明该错误在接收端,而不是在发送端ng程序。
    #include <stdio.h>
    #include <sys/socket.h>
    
    ...
    
    if (SendAllBytes(socket, &file_size, sizeof(file_size)) != 0) {
        // Error.
        return;
    }
    
    ...
    
    char buffer[1024];
    while (feof(file_stream) == 0) {
        const size_t bytes_read = fread(buffer, sizeof(*buffer), sizeof(buffer) / sizeof(*buffer), file_stream);
        // Upon successful completion, fread() shall return the number of elements
        // successfully read which is less than nitems only if a read error or end-of-file is encountered.
        // If size or nitems is 0, fread() shall return 0 and the contents of the array and the state of the stream remain unchanged.
        // Otherwise, if a read error occurs, the error indicator for the stream shall be set, and errno shall be set to indicate the error.
        // (Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/fread.html).
        if (bytes_read < sizeof(buffer) / sizeof(*buffer) &&
            ferror(file_stream) != 0) {
            // Error.
            return;
        }
    
        if (SendAllBytes(socket, buffer, bytes_read) != 0) {
            // Error.
            return;
        }
    }
    
    int SendAllBytes(int socket, const char *buffer, size_t bytes_to_send)
    {
        size_t total_bytes_sent = 0;
        while (bytes_to_send > 0) {
            const ssize_t bytes_sent = send(socket, &buffer[total_bytes_sent], bytes_to_send, 0);
            // Upon successful completion, send() shall return the number of bytes sent.
            // Otherwise, -1 shall be returned and errno set to indicate the error.
            // (Source: http://pubs.opengroup.org/onlinepubs/9699919799/).
            if (bytes_sent == -1) {
                // Error.
                return -1;
            }
    
            total_bytes_sent += bytes_sent;
            bytes_to_send -= bytes_sent;
        }
        return 0;
    }