Отправить размер файла, а затем сам файл - PullRequest
0 голосов
/ 22 апреля 2019

код на стороне клиента:

#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h>  
#include <netdb.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>

void error(char * msg){

    perror(msg);
    exit(0);

}

// Returns an string array from function
char *buff(const char *path){
    int end = 0;
    unsigned char * buf;
    int f_write = open(path,O_RDONLY);
    end = lseek(f_write,0,SEEK_END);
    lseek(f_write,0,SEEK_SET); 
    buf =(char*)malloc(sizeof(char*)*(end+1));
    read(f_write,buf,end);
    close(f_write);
    buf[end+1]= '\0'; 
    return buf;

}
     //connects to the socket
int connection(int portno,struct hostent * server,int sockfd){
    struct sockaddr_in serv_addr;
    int conn =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);
    conn = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    return conn;
}


int main(int argc, char *argv[]) {

    int sockfd = -1;
    int check =0;
    char projname[100]= "project1";
    int portno = -1;
    int conn = -1;
    int file_size =0;
    ssize_t len;
    int n = -1;
    struct hostent *server;
    char buffer[256];
    int fd =0;
    if(argc < 3){
        fprintf(stderr,"usage %s hostname port\n",argv[0]);
        exit(0);
    }
    // getting the portnumber
    portno = atoi(argv[2]);
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if(sockfd < 0){
        error("Error opening socket");

    }   
    // getting the hostname
    server = gethostbyname(argv[1]);

    if(server == NULL){
        fprintf(stderr,"Error no such host\n");
        exit(0);
    }
    conn = connection(portno,server,sockfd);
    if(conn < 0){

        printf("%s\n",strerror(errno)); 

    }
    int path = open("text.txt",O_CREAT | O_WRONLY, 0644);
    if(path < 0){
        printf("%s\n",strerror(errno));
    }
    int remain_data = file_size;
    printf("Printing out the file size ");
    printf("%d\n",file_size);
    char *buffer1 = (char*)malloc(sizeof(char)*file_size+1);
    len = recv(sockfd,buffer1,BUFSIZ,0);
    printf("%d",len);
    buffer1[file_size]= '\0';
    printf("printing the sentence\n");
    printf("%s\n",buffer1);

    int total_read_bytes =0;
    int nread =0;

     return 0; 
}

код на стороне сервера

#include <unistd.h> 
#include <stdio.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <dirent.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <sys/socket.h>

void error(char * msg){

    perror(msg);
    exit(1);

}

 int main(int argc, char const *argv[]){
    int sockfd =-1;
    int newsockfd = -1;
    int portno = -1;
    int clilen = -1;
    int remain_data =0;
    char buffer[300];
    char buffer1[300];
    int peer_socket = -1;
    struct sockaddr_in serv_addr,cli_addr;
    int n = -1;
    struct stat file_stat;
    char file_size[256];
    ssize_t  len;
    int sent_bytes =0;
    int path = open("project1/text.txt",O_RDONLY);
    read(path,buffer1,30);
    buffer1[31]= '\0';
    printf("%s\n",buffer1);
    sockfd = socket(AF_INET, SOCK_STREAM, 0);

    if(sockfd <0){
            error("Error opening socket");
    }

    bzero((char*) &serv_addr,sizeof(serv_addr));

    portno=atoi(argv[1]);

    serv_addr.sin_family = AF_INET;

    serv_addr.sin_addr.s_addr = INADDR_ANY;

    serv_addr.sin_port = htons(portno);

    if(bind(sockfd,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0){
            error("Error on Binding");

    }

    listen(sockfd,5);
    int fd = open("project1/text.txt",O_RDONLY);
    fstat(fd,&file_stat);

    clilen = sizeof(cli_addr);

    peer_socket = accept(sockfd,(struct sockaddr *)&cli_addr, &clilen);

    sprintf(file_size,"%d",file_stat.st_size);
    //sends file size
    len = send(peer_socket,file_size,sizeof(file_size),0);

    if(peer_socket <0){

            error("Error on accept");       

    }

    off_t offset = 0;
    remain_data = file_stat.st_size;
    //send the file
    while(((sent_bytes=sendfile(peer_socket,fd,&offset,remain_data))>0) &&( remain_data>0)){
            fprintf(stdout,"1.Server sent %d bytes from files data, offset is now : %d and remaining data = %d\n",sent_bytes, offset,remain_data);
            remain_data -=sent_bytes;
            fprintf(stdout, "2. Server sent %d bytes from files data, offest is not: %d and remaing data = %d\n",sent_bytes, offset,remain_data);

    }
    return 0;
}

Я могу получить размер моего файла со стороны сервера, но я не могу получить содержимое файла со своего сервера на стороне клиента. Мой клиент распечатывает пустое место, где должны находиться данные файла, я не знаю, правильно ли я использую функцию recv для файла. П.С. Я понимаю, что я должен закрыть розетки, когда закончу.

1 Ответ

2 голосов
/ 22 апреля 2019

В целях безопасности и надежности вы должны проверить возвращаемые значения всех стандартных функций библиотеки, которые вы вызываете, чтобы проверить ошибки. Однако для recv() и read() необходимо проверить и соответствующим образом обработать возвращаемые значения для правильности . Эти функции не гарантируют передачу полного количества запрошенных байтов, и для сетевых подключений достаточно распространено, что они этого не делают. Если вы хотите полностью передать определенное количество байтов, вы должны быть готовы использовать несколько вызовов recv() или read() для этого, обычно вызывая функцию в цикле.

Вы не проверяете возвращаемое значение вашего вызова recv(), поэтому, если у вас короткое чтение - или если есть ошибка или если удаленная сторона закрывает соединение, ничего не отправляя - тогда ваш клиент не будет обратите внимание, и просто выведет любой мусор, который окажется в буфере.

...