当我发送文件到客户端它被损坏,并以字节的大小更高。
我有一个在Windows上运行的服务器的版本,完美的工作,但我没有在Linux上有相同的结果。
磁盘上的文件大小可能是将大小(以字节为单位)发送到在另一个平台上运行的客户端的错误?
客户端完美的工作,正如我所说我有一个在Windows上运行此服务器的版本,唯一的区别是fread: Size = fread(mfcc, 1, min(sizeof(mfcc), FileSize), fp);
fread函数是否正确使用?
专家可以分析和帮助find错误?
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; }
我认为你的问题在这里:
iResult = send(client[iD].socket, (const char*)&Size_Send, Size_Send, 0);
你用这个调用发送Size_Send字节(大部分是Size_Send变量结束之后的杂项内存),而不是你想要的,也就是发送sizeof(long)字节。 用sizeof(long)替换上面第二行的Size_Sent的第二个实例,你会得到一个更好的结果。
假设使用POSIX套接字(IEEE标准1003.1,2013版) 。
我们来考虑下面的几段代码:
发送文件大小。
// 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; }
发送“块”。
if (send(client[iD].socket, Block, BytesRead, 0) != BytesRead) { errno_message.append((char*)strerror(errno)); FUNCTION_LOG(errno_message); fclose(fp); return 1; }
send()
函数并不保证所有的数据都会被“立即”发送(即使用单个函数调用):
返回值
成功完成后,
send()
应返回发送的字节数。 否则,返回-1,并errno
来指示错误。– 发送 – 在套接字上发送消息,Open Group Base Specification Issue 7,IEEE Std 1003.1,2013 Edition 。
因此, 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; }
考虑使用固定宽度的整数类型来增强可移植性。 在所描述的情况下,文件大小不是由固定宽度整数类型表示的。