簡體   English   中英

讀取可執行文件的字符以在C中進行文件傳輸

[英]Read the characters of an executable for file transfers in C

因此,最近在一個課程項目中,我決定為自己創建一個程序,該程序可以使用套接字在局域網上傳輸文件並將其集成到linux操作系統中(在這種情況下,我所做的就是將其添加到上下文菜單中)。服務器。

它的運作方式本質上是

Server is waiting.
Client connects.
Client sends a message of 1024 length with the first 4 characters reserved
The first 4 characters are used to store an int which will state the length of the message

server recieves them, writes them, then waits for the next block
when the server recieves a message where the length is 0  
it ends the transfer and closes the files

這完美地適用於文本文件。 由於提供了有用的反饋意見,我對上一個代碼進行了改進,因此我設法創建了一種操作系統可以實際識別文件擴展名的東西,而與類型無關。 但是,對於png之類的東西,它們顯示為黑色;對於exe,則它們會立即出現段錯誤。

無論文件類型如何,我在閱讀和書寫中可以進行哪些更改以使其正常工作? 我不確定要去哪里,因為我應該有的工作

附加信息:我使用C進行編碼。要打開文件,請使用fopen,fgetc和fputc。 這是我的服務器代碼所發揮的作用:

          while (1){

     n = read(newsockfd,message,1024);
     if (n < 0) {
        fclose(fptr2);
        error("ERROR reading from socket");
        }
    //The first 4 bytes/characters are used to store the length.
    //I read them by getting a pointer to the first char and then reading it as
    //an int by casting it. This works with no problem
    char *p=&message;
    int *p2=(int*)p;
    int length=*p2;
     //Checks if the length is 0, if so, exit
     if (length==0)
        break;
    //writes to the file
        for (int i=4;i<length;i++){
          fputc(message[i], fptr2);
    }

     n = write(newsockfd,"Ready",5);
     if (n < 0) 
         error("ERROR writing to socket");
     bzero(message,255);
     }

     fclose(fptr2);
     //n = write(newsockfd,"I got your message",18);
     //if (n < 0) error("ERROR writing to socket");
     printf("Done.\n");
     return 0; 
}

從我的客戶端執行,該客戶端讀取文件然后發送。

    while (finished!=0&&c!=EOF)
{

   for (int i =4;i<1024;i++)
   {
       if (c==EOF)
       {
    char* p=&message;
    int* pi=(int*)p;
    *pi=i;
    finished=0;
    //printf("length is:%d\n",i);
    break;
    }
    //printf("%c",c);
       message[i]=c;
       //fputc(c, fptr2);
       c = fgetc(fptr1);    
   }
if (finished!=0) 
{
char* p=&message;
int* pi=(int*)p;
*pi=1024;
}
   n = write(sockfd,message,1024);
   if (n < 0) 
     {
       fclose(fptr1);
       error("ERROR writing to socket");
     }
   bzero(message,1024);
   //reading
   n = read(sockfd,buffer,255);
  if (n < 0) 
     error("ERROR reading from socket");
}

0x00是二進制文件的有效字符,因此當您看到一個字符時就不能“停止” [就像您可以為字符串一樣]。

您將數據包的第一個字符用作EOF標記(即非零表示有效數據,零表示EOF)。 但是,請注意,數據包中的第一個數據字符可能為零,因此您必須使用一個不包含數據字符的字節“ header”,而僅使用“ stop”標志char [如果您願意]:

while (1) {
    // Reading
    n = read(newsockfd, message, 1023);
    if (n < 0) {
        fclose(fptr2);
        error("ERROR reading from socket");
    }

    // Checks if the first character is null, if so, exit
    if (message[0] == 0)
        break;

    // writes to the file
    // NOTE: now the data starts at offset 1!
    int i = 1;
    for (;  i < n;  ++i) {
        fputc(message[i], fptr2);
    }

    i = 0;
    n = write(newsockfd, "Ready", 5);
    if (n < 0)
        error("ERROR writing to socket");
    bzero(message, 1023);
}

fclose(fptr2);

但是,一種更簡單的方法是只讀取直到長度返回零:

while (1) {
    // Reading
    n = read(newsockfd, message, 1024);

    // end of data
    if (n == 0)
        break;

    // error
    if (n < 0) {
        fclose(fptr2);
        error("ERROR reading from socket");
    }

    // writes to the file
    fwrite(message,1,n,fptr2);

    i = 0;
    n = write(newsockfd, "Ready", 5);
    if (n < 0)
        error("ERROR writing to socket");
    bzero(message, 1023);
}

fclose(fptr2);

簡而言之,要使此功能生效,最重要的更改是在程序停止讀取時進行更改。 EOF只是-1,在文本文件中,這沒問題,但是在其他文件中,此值可能在任何地方都可以找到。 為了正確讀取字符,您必須首先獲取文件長度,然后簡單地讀取字符直到達到該長度。

fseek(fptr1, 0L, SEEK_END);
int sz = ftell(fptr1);
rewind(fptr1);
int count=0;
while (count!=sz)
{
//other code left out for simplicity
c = fgetc(fptr1);
count++;
}

進行此更改后,我的程序可以正常運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM