2014-09-03 90 views
0

我將在此重新提示整個問題,以便它可以負責。通過TCP/IP連接發送二進制文件

我能夠在不使用套接字的同一臺機器上完美地複製二進制文件,而只是製作一個簡單的複製功能。試圖實現此代碼複製到TCP/IP連接,但無法使其工作。

FILE *filehandle = fopen("imagefile.jpg", "rb"); 
FILE *dest =fopen("imagecopy.jpg", "wb"); // copied image file 
fseek(filehandle, 0, SEEK_END); 
unsigned long filesize = ftell(filehandle); 
char *buffer = (char*)malloc(sizeof(char)*filesize); 
rewind(filehandle); 
int bytesread = fread(buffer, sizeof(char), filesize, filehandle); 
for(int i=0; i<filesize; i++) 
{ 
    fputc(buffer[i], filehandle); // copies all the contents to dest 
} 

上面的代碼完美地適用於在計算機上覆製圖像文件,但是當實現在服務器上覆制時,很難去處理它。

我試圖從服務器發送圖像文件到客戶都已經手動進行C中的文件的長度由服務器發送時,它的只知道到服務器發送文件,因此緩衝區在服務器中動態生成的,這樣的事情:

服務器

fseek(filehandle, 0, SEEK_END); 
long filesize = ftell(filehandle); // file could be 11000bytes 
char *buffer = (char*)malloc(sizeof(char)*filesize); // char buffer with 11000 bytes to store the data from the file. 
// then I call the send() function 
rewind(filehandle); // go back to beginning 
send(clientsocket, buffer, filesize, 0); // this is being sent perfectly, no errors because in the actual code, I am checking for errors 

CLIENT

// here is where I don't understand how to dynamically allocate the 11000 bytes to store the data in a client buffer 
// the filesize is not necessarily going to be 11000 so need to dynamically allocate 
// I did the following: 
#define BUFSIZE 10 
FILE *filehandle = fopen("imagefile.jpg", "wb"); // image file created by client 
char *buffer = (char*)malloc(sizeof(char)*BUFSIZE); 
int bytesread = recv(buffer, 1, strlen(buffer), 0); 
if(bytesread > 0) 
{ 
    printf("Bytes read: %d\n", bytesread); // bytes read is 5 
    printf("Buffer: %s\n", buffer); // but buffer shows all the binary text like it normally would 
    // when I try to store buffer in a file, it doesn't put full buffer because only 5 characters are written 
    for(int i=0; i<bytesread; i++) 
    { 
     fputc(buffer[i], filehandle); // this doesn't create full image 
    } 
} 

如何動態分配服務器發送的11000字節?

+2

你在問爲什麼你沒有顯示的代碼不起作用? – 2014-09-03 00:41:49

+2

未定義的行爲就是 - _undefined_。它不需要崩潰。 – SLaks 2014-09-03 00:42:35

+0

目前還不清楚爲什麼你使用'printf('%s''顯示一個圖像文件 – 2014-09-03 00:42:40

回答

11

您需要循環發送和接收。根據您的要求,send()recv()都不保證發送/讀取儘可能多的字節。

您還應該在文件數據之前發送文件大小,以便接收器知道需要多少字節以及何時停止讀取。

嘗試更多的東西是這樣的:

服務器

bool senddata(SOCKET sock, void *buf, int buflen) 
{ 
    unsigned char *pbuf = (unsigned char *) buf; 

    while (buflen > 0) 
    { 
     int num = send(sock, pbuf, buflen, 0); 
     if (num == SOCKET_ERROR) 
     { 
      if (WSAGetLastError() == WSAEWOULDBLOCK) 
      { 
       // optional: use select() to check for timeout to fail the send 
       continue; 
      } 
      return false; 
     } 

     pbuf += num; 
     buflen -= num; 
    } 

    return true; 
} 

bool sendlong(SOCKET sock, long value) 
{ 
    value = htonl(value); 
    return senddata(sock, &value, sizeof(value)); 
} 

bool sendfile(SOCKET sock, FILE *f) 
{ 
    fseek(f, 0, SEEK_END); 
    long filesize = ftell(f); 
    rewind(f); 
    if (filesize == EOF) 
     return false; 
    if (!sendlong(sock, filesize)) 
     return false; 
    if (filesize > 0) 
    { 
     char buffer[1024]; 
     do 
     { 
      size_t num = min(filesize, sizeof(buffer)); 
      num = fread(buffer, 1, num, f); 
      if (num < 1) 
       return false; 
      if (!senddata(sock, buffer, num, 0)) 
       return false; 
      filesize -= num; 
     } 
     while (filesize > 0); 
    } 
    return true; 
} 

FILE *filehandle = fopen("imagefile.jpg", "rb"); 
if (filehandle != NULL) 
{ 
    sendfile(clientsocket, filehandle); 
    fclose(filehandle); 
} 

CLIENT

bool readdata(SOCKET sock, void *buf, int buflen) 
{ 
    unsigned char *pbuf = (unsigned char *) buf; 

    while (buflen > 0) 
    { 
     int num = recv(sock, pbuf, buflen, 0); 
     if (num == SOCKET_ERROR) 
     { 
      if (WSAGetLastError() == WSAEWOULDBLOCK) 
      { 
       // optional: use select() to check for timeout to fail the read 
       continue; 
      } 
      return false; 
     } 
     else if (num == 0) 
      return false; 

     pbuf += num; 
     buflen -= num; 
    } 

    return true; 
} 

bool readlong(SOCKET sock, long *value) 
{ 
    if (!readdata(sock, value, sizeof(value))) 
     return false; 
    *value = ntohl(*value); 
    return true; 
} 

bool readfile(SOCKET sock, FILE *f) 
{ 
    long filesize; 
    if (!readlong(sock, &filesize)) 
     return false; 
    if (filesize > 0) 
    { 
     char buffer[1024]; 
     do 
     { 
      int num = min(filesize, sizeof(buffer)); 
      if (!readdata(sock, buffer, num)) 
       return false; 
      int offset = 0; 
      do 
      { 
       size_t written = fwrite(&buffer[offset], 1, num-offset, f); 
       if (written < 1) 
        return false; 
       offset += written; 
      } 
      while (offset < num); 
      filesize -= num; 
     } 
     while (filesize > 0); 
    } 
    return true; 
} 

FILE *filehandle = fopen("imagefile.jpg", "wb"); 
if (filehandle != NULL) 
{ 
    bool ok = readfile(clientsocket, filehandle); 
    fclose(filehandle); 

    if (ok) 
    { 
     // use file as needed... 
    } 
    else 
     remove("imagefile.jpg"); 
} 
+0

緩衝區1024對於服務器發送的文件大小是不是太小? – Hawk 2014-09-03 08:00:42

+0

不,因爲接收器正在循環,以1024字節塊讀取,直到收到文件末尾。 – 2014-09-03 16:06:53

+1

您需要停止嘗試分配一個緩衝區來保存整個文件。其一,這並不高效。二,浪費大量文件的時間和內存。在您讀取源文件時,將源文件分塊發送。在收到目標文件時,將其分塊寫入。 – 2014-09-03 16:25:29

2

我們可以避開包含圖像大小的標題,但我們只是讀到發送數據的末尾。關於緩衝區大小,我們可以使用一個固定的數字,例如10 * 1024,當我們從服務器接收到一些數據時,我們會根據實際接收的數據長度將其保存到一個文件中。

// please open a file ... 
FILE * fp; 
// ... 
const int LENGTH = 10 * 1024; 

int len = 0; 
char * buffer = (char *)malloc(LENGTH); 
while ((len = recv(socket, buffer, LENGTH, 0)) > 0) { 
    fwrite(buffer, 1, len, fp); 
} 
free(buffer); 
// close the file 

@ T.C:我想根據從案例圖像過大,保存客戶端的內存裏面的服務器發送的大小,我們不能分配的緩衝區。沒有提到服務器是假的,並且打算進行任何攻擊。

+0

由LENGTH分配的內存是10240字節,我認爲..但圖像文件是11656字節,這將導致文件不能被完全複製。 – Hawk 2014-09-03 08:04:22

+0

@Hawk:你不斷髮表評論,建議你不理解循環如何工作。這是真的嗎?如果是這樣,你需要停止你正在做的事情,並回到學習基礎編程的基礎知識。這段代碼將繼續讀取'LENGTH'塊,將每個塊寫入'fp',直到套接字關閉或者'recv()'失敗並出現錯誤。這意味着這段代碼要求發送者在完成發送文件時關閉套接字,而不事先發送文件大小。 – 2014-09-03 16:31:01

相關問題