gpt4 book ai didi

c++ - 大文件上的 fwrite 字节损坏

转载 作者:行者123 更新时间:2023-11-28 03:19:56 24 4
gpt4 key购买 nike

我正在开发一个关于客户端和服务器的 c++ 程序(最像练习课),使用 HTTP 协议(protocol),用户给客户端一个文件名和大小(字节),然后客户端创建 n 个线程,每个线程一个向服务器请求特定数量的字节,服务器接受命令,客户端接收数据并将所有数据放在一起。

我的程序可以很好地处理小文件(100kb - 200kb),但是当我尝试从服务器发送大文件(例如 Mb)时,所有字节都已收到,但最终文件已损坏,每个线程都有自己的 init 和结束字节数并创建一个名为“file_n.txt”的文件,因此在将所有字节放在一起时字节顺序没有问题,最终损坏的文件与原始文件的字节数相同(所有字节都已收到,我还检查了服务器日志,了解线程要求的字节间隔)但它的 hexdump 是不同的(显然)。

您认为 fwrite 函数与此问题有关吗?如果是的话,请给我指出正确的方向会很酷,我正在努力解决这个问题,这是我的 client.cpp 代码

#include <pthread.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <iostream>
#include <string>
#include <sstream>

using namespace std;
const int MAX_HEADER_SIZE = 1000;
int threadsEnd = 0;

struct bytes
{
int initByte;
int endByte;
int bufferSize;
int id;
char * port;
char * ip;
char * image;
};

void error(const char *msg)
{
perror(msg);
exit(0);
}

void * request_bytes (void * parameters)
{
struct bytes * p = (struct bytes *) parameters;

int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;

int totalBuffer = MAX_HEADER_SIZE + p->bufferSize + 1;
int totalBodyContent = p->bufferSize + 1;

char buffer[totalBuffer];
char bodyContent[totalBodyContent];

portno = atoi(p->port);
server = gethostbyname(p->ip);

sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&serv_addr.sin_addr.s_addr, server->h_length);
serv_addr.sin_port = htons(portno);

if (connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr)) < 0)
error("ERROR connecting");


ostringstream init,end;
init << p->initByte;
end << p->endByte;

string HttpRequestString = string("POST / HTTP/1.1\r\n")
+ string("Host: ") + p->ip + string("\n")
+ string("Connection: Close\n")
+ string("Content-Length: 4\n")
+ string("Content-Type: txt\n\n")
+ string("nombre=") + p->image + string("&inicio=") + init.str() + string("&fin=") + end.str() + string("\n");

const char * HttpRequest = HttpRequestString.c_str();

n = write(sockfd,(void *)HttpRequest, strlen(HttpRequest));

if (n < 0)
error("ERROR writing to socket");

bzero(buffer,(MAX_HEADER_SIZE + p->bufferSize));
int headerEndDetermined = 0, bodyEnd = 0;

int x = 1;
int bodyInit = 1;
int total_bytes = 0;

n = read(sockfd,buffer,((MAX_HEADER_SIZE + p->bufferSize) - 1));

if (n < 0)
error("ERROR reading from socket");

for(; x < strlen(buffer); x++)
if(buffer[x - 1] == '\n')
if(buffer[x] == '\n')
{
headerEndDetermined = 1;
bodyInit = x + 1;
break;
}


for(x = 0; x < p->bufferSize ; x++)
{
bodyContent[x] = buffer[bodyInit];
bodyInit++;
}

//Escritura de archivo
char filename[32];
snprintf(filename, sizeof(char) * 32, "file%i", p->id);

FILE * pFile;
pFile = fopen (filename,"wb");
if(pFile != NULL)
{
fwrite (bodyContent,1,sizeof(bodyContent) - 1,pFile);
fclose (pFile);
}

close(sockfd);
threadsEnd++;

return NULL;
}

int main (int argc, char *argv[])
{
if (argc < 5) {
fprintf(stderr,"uso %s hostname puerto image_name bytes\n", argv[0]);
exit(0);
}

int globalByte = atoi(argv[4]);
int threadRequest = 10;
int requestBytes = (globalByte / threadRequest);
int globalInitialByte = 1;
int globalEndByte = requestBytes;
int x = 0, i = 1;
int totalBytesRequested = 0;

pthread_t request[threadRequest];

for(; x < threadRequest; x++){
struct bytes request_args;

request_args.initByte = globalInitialByte;
request_args.endByte = globalEndByte;
request_args.bufferSize = requestBytes;
request_args.id = x + 1;

globalInitialByte = globalEndByte + 1;
globalEndByte = globalEndByte + requestBytes;

if(x == (threadRequest - 1))
{
if((totalBytesRequested + requestBytes) < globalByte)
{
request_args.endByte = globalByte;
request_args.bufferSize = requestBytes + (globalByte - (totalBytesRequested + requestBytes));
}
}
request_args.ip = argv[1];
request_args.port = argv[2];
request_args.image = argv[3];

pthread_create (&request[x], NULL, &request_bytes, &request_args);
pthread_join (request[x], NULL);

totalBytesRequested += requestBytes;
}

/*do
{
cout<<"Threads completos: "<<threadsEnd<<endl;
}while(threadsEnd < threadRequest);*/

string createFileString = string("cat ");
for(; i <= threadRequest; i++)
{
ostringstream filen;
filen << i;
createFileString = createFileString + string("file") + filen.str() + string(" ");
}
createFileString = createFileString + string("> new_") + argv[3];
system(createFileString.c_str());

return 0;
}

抱歉我的语法不好:p。

最佳答案

你有很多错误。

  1. HTTP 协议(protocol)规定行必须以“\r\n”而非“\n”结尾。

  2. 您指定了四个字节的内容长度,但您的内容比这长。

  3. 当您的代码已经知道事物的大小时,不要使用 sizeofstrlen。这会给你带来麻烦。

  4. 您只调用一次read。您需要继续调用 read 直到收到所有数据。

  5. 您指定了 HTTP 1.1 合规性,但您的代码实际上并不符合 HTTP 1.1 规范。例如,如果您接收到带有分块编码的数据,您的代码就会崩溃。 HTTP 1.1 客户端需要支持分块编码。 “所有 HTTP/1.1 应用程序必须能够接收和解码分块传输编码[.]”-- RFC2616 3.6.1 .

关于c++ - 大文件上的 fwrite 字节损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15738999/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com