2013-11-01 205 views
-1

我正在嘗試構建服務器客戶端代碼。客戶可以從服務器上下載任何文件,但我有一個二進制文件無法傳輸二進制文件

問題,這是我的客戶端代碼:

#include <stdio.h> 
#include<sys/types.h> 
#include<sys/socket.h> 
#include<sys/time.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#include<string.h> 
#include<errno.h> 
#include<stdlib.h> 
#include<fcntl.h> 
#define Max_len 1025 
//-------------------------- to replay for pecific secret simpol 0x55 
char secret(char * str) 
{ 
    char sub=0x55; 
    if(sub==str[0]) 
     { 
      sub=0xAA; 
      return sub; 
     } 
    else 
     { 
      printf("server does not give the right secret code\n"); 
      exit(0); 
     } 
} 
//-------------------------warraper function for perror 
void error(char * str) 
{ 
    perror(str); 
    exit(0); 
} 
int main (int nof_arg, char **argv) 
{ 
    //------------------------define data types 
    int sockfd,number,portno,val=0,fil_fd; //to store the file descreptore of socket 
    char rec_lin [Max_len],f_name[20]="\0",car; // act as buffer 
    struct sockaddr_in servaddr; 
    char * read_one; 
    FILE * file_ptr; //------------------------ welcome message identife the writer 
    printf("\n\t Welcom the client \n\t Name: Eftikhar Emad \n\t ID: 20100175003\n\tsection #1: 9:15-10:15\n\n"); 
    //------------------------ prepair the client to start connection 
    if (nof_arg < 3)   //check the number of entered arregument 
     error("you need the IP and port number to connect please check them again\n"); 

    portno=atoi(argv[2]);   // convert the port from string to int 
    if((portno<=22000) || (portno>=23000)) //check to see if the port numberif valiled 
     error("your port number is out of range please try agin start with 22XXX\n"); 

    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0) //socket creation 
     error("Socket creation error"); 

    bzero(&servaddr,sizeof(servaddr));  //static define for the server 
    servaddr.sin_family=AF_INET; 
    servaddr.sin_port = htons(portno); 

    if(inet_pton(AF_INET,argv[1],&servaddr.sin_addr)<=0)//it can be used to check 
     error("inet_pton error "); 

    if((connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr)))<0)//connection 
     error("connect error"); 

    //------------------------------------start define the server valited 
    bzero(rec_lin,sizeof(rec_lin)); 
    read(sockfd,rec_lin ,sizeof(rec_lin)); 
    printf("received the byte 0x55 from the server\n"); //will readonly one char 
    car=secret(rec_lin); 
    printf("Sending ack 0xAA to the server\n"); 
    bzero(rec_lin,sizeof(rec_lin)); 
    snprintf(rec_lin,sizeof(rec_lin),"%c",car); 
    write(sockfd,rec_lin,1);   //send 0xAA if 0x55 


    //-------------------------------------print the list from server 
    read(sockfd,rec_lin,sizeof(rec_lin)); 
    while(rec_lin[0]!= '\0') 
     { 
      read(sockfd,rec_lin,sizeof(rec_lin)); 
      printf("%s\n",rec_lin); 
     } 


    //-------------------------after know the server start to ask and send file name 
    printf("enter file name to download : "); 
    gets(f_name);     //rad file name from user 
    snprintf(rec_lin,sizeof(rec_lin),"%s",f_name); 
    write(sockfd,rec_lin,sizeof(rec_lin));  //send the file name to server 
    bzero(rec_lin,sizeof(rec_lin)); 
    //--------------------------------------check server reply 0/1 for finding or not 
    read(sockfd,rec_lin,/*sizeof(rec_lin)*/1); 
    int p; 
    if(rec_lin[0]==0x31) //if file found inform the user,start,ending msg 
     {   //no creation to file unless it found on server 
      printf("Received 1 from server %s exists\nStart downloading the file\n",f_name); 
      fil_fd=open(f_name,O_RDWR| O_CREAT, S_IRUSR | S_IRGRP | S_IROTH); 
      while((val=read(sockfd,rec_lin,sizeof(rec_lin)-1))>0) 
       { 
        p=strlen(rec_lin); 
        // rec_lin[val]='\0'; 
        write(fil_fd,rec_lin,/*sizeof(rec_lin)*/p+1); 
        bzero(rec_lin,1049); 
       } 
      printf("Done Downloadng the file.......exit\n\n"); 
      close(fil_fd); 
     } 
    else   //if file not found terminate the connection 
     { 
      printf("file not found get ... connection will closed\n\n"); 
     } 
    // -----------------------------terminate connection if it Done in the right way 
    close(sockfd); 
    return 0; 

} 

,這是我的服務器代碼:

#include<stdio.h> 
#include<errno.h> 
#include<arpa/inet.h> 
#include<string.h> 
#include<netinet/in.h> 
#include<sys/types.h> 
#include<sys/socket.h> 
#include<stdlib.h> 
#include<fcntl.h> 
#include<netdb.h> 
#include<dirent.h> 
#define Max_len 1025 
void error (char * str) 
{ 
    perror(str); 
    exit(0); 
} 
int main (int argc, char ** arg) 
{ 
    //------------------------- define data type 
     int listenfd,connfd,clilen,portno,fil_fd,n; 
    char buff[Max_len], *str,f_name[100],car=0xAA,h_IP[30],h_P[20]; 
    struct sockaddr_in servaddr,cliaddr; 
    DIR * ddir; 
    struct dirent * ndir; 
    //------------------------- socket intinalizing 
    printf("\n\t Welcom the server \n\t Name: Eftikhar Emad \n\t ID: 20100175003\n\t section #1: 9:15-10:15\n"); 

    if(argc != 2)   //of user forget to insert the port number 
     error("missing port number to complet establishment\n"); 

    portno=atoi(arg[1]);  //convert the port to int and check if it was within the rang 
    if((portno<=22000) || (portno>=23000)) 
     error("your port number not valid .... pleas insert one in reng (22000,22999)\n"); 

    listenfd=socket(AF_INET,SOCK_STREAM,0);  //creat the listing socket 
    bzero((char *)&servaddr ,sizeof(servaddr)); 
    servaddr.sin_family=AF_INET;  //Ipv4 
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY); 
    servaddr.sin_port=htons(portno); 

    bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));//bind the liten socket to specific port 
    listen(listenfd,5); 
    //-------------------------- server start to wait to handle requests 
    for(;;) 
     { 
      printf("server wait for connections\n"); 
      bzero((char *)&cliaddr ,sizeof(cliaddr)); //clear the previus client information 
      clilen=sizeof(cliaddr);    //client informaton container 
      connfd=accept(listenfd,(struct sockaddr *)&cliaddr,&clilen); 
      int f=fork();  //start of fork() 
      if(f==0) 
       { 

        close(listenfd); 
        if(connfd<0) 
         error("error in accept this connection\n"); 
        //---------------------------------------  //start the secret hand chacking 
        bzero(buff,sizeof(buff)); 
        getnameinfo((struct sockaddr *)&cliaddr,sizeof(cliaddr),h_IP,sizeof(h_IP),h_P,sizeof(h_P),0); 
        printf("Sending byte 0x55 to client with IP %s and port of %s\n",h_IP,h_P); 
        //get the IP AND port# of the client 
        snprintf(buff,sizeof(buff),"%c",0x55); 
        write(connfd,buff,sizeof(buff)); 
        //---------------------------------------  //read file name 
        car=0xAA; 
        read(connfd,buff,sizeof(buff)); 
        printf("received 0XAA from client \n"); 
        if(car==buff[0]) 
         { 
          //------- send the list to the client 
          snprintf(buff,sizeof(buff),"select file to download it\n"); 
          write(connfd,buff,sizeof(buff)); 
          ddir=opendir("."); 
          if(ddir==NULL) 
           {printf("error\n");exit(0);} 
          while((ndir=readdir(ddir))!=NULL) 
           {//printf("%s\n",ndir->d_name); 
            snprintf(buff,sizeof(buff),"%s",ndir->d_name); 
            printf("%s\n",buff); 
            write(connfd,buff,sizeof(buff)); 
           } 
          write(connfd,"\0",1); 
          closedir(ddir); 


          read(connfd,buff,sizeof(buff));  //get the name after get 0xAA 
          strncpy(f_name,buff,sizeof(buff)-1); 
         } 
        else 
         { printf("this is not secure client\n");break;} 

        //-------------------------------------- if file found send 1 else 0 
        fil_fd=open(f_name,O_RDONLY);  //file opent to be read only 
        if(fil_fd < 0) 
         { 
          snprintf(buff, sizeof(buff),"%d",0); 
          write(connfd,buff,1); 
          printf("file is not found\n");  //retminate connection only 
          break; 
         } 
        else 
         { 
          snprintf(buff, sizeof(buff),"%d",1); 
          write(connfd,buff,sizeof(buff)); 
          printf("file exists.Send %s to client\n",buff); 
          //-----------------------------------reading and sending 
          while((n=read(fil_fd,buff,sizeof(buff)-1))>0) 
           { buff[n]='\0'; 
            write(connfd,buff,/*sizeof(buff)*/n+1); //sending the file process 
            bzero(buff,sizeof(buff)); 
           }//end of uploading 
          printf("end download thf file"); 
          close(fil_fd); 
         }//end of if_else 
        close(connfd); 
        exit(0); 
       }//end of child code 
      else 
       { 
        //wait(NULL); 
        printf("-------------------------------\n"); 
        close(connfd); 
       } 
     }//end of for() 
    //--------------------------------------------prepair the server connection 
    close(listenfd); 
    exit(0); 

    return 0; 
}//main() 

此代碼工作如果我將它與「file.txt」一起使用,那很好。 我想使用二進制文件而不使用fread()fwritefopen。 有什麼辦法可以做到嗎?

+0

當您嘗試下載二進制文件錯在何處? – Barmar

+0

我無法在同一臺機器上進行測試,因此讀取和寫入將在同一個文件中 – Haboosh

+1

這是否應該是我的問題的答案?無論如何,看起來問題可能與服務器在寫入連接之前在'buf'結尾添加'\ 0'有關。你爲什麼這樣做?只有字符串需要追蹤空值,而不是字節數組。 – Barmar

回答

1

您無法編寫忽略read(),recv()等返回值的正確聯網軟件。這些函數返回-1表示錯誤,零表示流結束或讀取計數。你現在的代碼忽略了所有三種可能性,它也假設read()填充緩衝區。沒有任何地方這麼說。

編輯:我應該說清楚,這同樣適用於從任何來源閱讀,而不僅僅是網絡。

+0

哦謝謝很多 – Haboosh

0

我的問題是...使用open()將創建文件數據,所以當執行二進制文件將給「不能執行二進制文件」。

解決方法:使用fopen(file_name,"r+b")可以創建文件以二進制文件在不同的方式比文本文件