我正在開發一個關於客戶端和服務器的C++程序(最像是一個練習類),使用HTTP協議,用戶給客戶端一個文件文件名和大小(字節),然後客戶端創建n個線程,每個線程向服務器請求特定數量的字節,服務器參與訂單,客戶端接收數據並放在一起。在大文件上使用fwrite進行字節損壞
我的程序對於小文件(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;
}
對不起我的語法錯誤:對。
N個線程寫入的N個單個文件是否包含正確的數據? – alk
如果原始文件是1000字節,並且我創建10個線程每個「file_n。txt「有100字節,所以尺寸很好,我不知道內容(它適用於小文件),但讓我再次檢查與hexdump(個人文件),我會告訴你。 – Alevsk
是的,去檢查那些N文件,因爲這基本上是爲了弄清故障的根本原因在於服務器端文件斬波器,發送器,接收器還是客戶端文件合併器。 – alk