Linux服务器,向windows客户端发送文件(Socket)

时间:2015-10-01 04:08:58

标签: c++ c linux sockets

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

我在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;
}

2 个答案:

答案 0 :(得分:3)

我认为你的问题在这里:

iResult = send(client[iD].socket, (const char*)&Size_Send, Size_Send, 0);       

您正在通过此调用发送Size_Send字节(大多数是在Size_Send变量结束之后的其他内存),而不是您可能想要的,即发送sizeof(长)字节。用sizeof(long)替换上面一行中Size_Sent的第二个实例,你会得到更好的结果。

答案 1 :(得分:2)

假设使用POSIX sockets (IEEE Std 1003.1, 2013 Edition)

分析

让我们考虑以下几段代码:

  1. 发送文件大小。

    // 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;
    }
    
  2. 发送&#34;块&#34;。

    if (send(client[iD].socket, Block, BytesRead, 0) != BytesRead)
    {
        errno_message.append((char*)strerror(errno));
        FUNCTION_LOG(errno_message);
        fclose(fp);
        return 1;
    }
    
  3. send()功能并不保证所有数据都会立即发送&#34;&#34; (即使用单个函数调用):

      

    返回值

         

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

         

    - send - send a message on a socket, The Open Group Base Specifications Issue 7, IEEE Std 1003.1, 2013 Edition

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

    解决方案

    必须使用send()函数的返回值来实现循环,以发送fread()函数调用先前读取的所有字节。 请参阅SendAllBytes()函数的实现。它应该用于纠正这两段代码(参见&#34;分析&#34;部分)。

    以下代码仅作为示例考虑:

    #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;
    }
    

    便携性说明

    考虑使用fixed-width integer types来增强可移植性。在所描述的情况下,文件大小不由固定宽度整数类型表示。