Отправка файлов и данных между клиентом и сервером с помощью сокетов в C - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь выполнить несколько функций, используя следующие два сценария. Я пытаюсь загрузить файлы с клиента на сервер, загрузить файлы с сервера на клиент, изменить каталог сервера и затем загрузить список файлов в этом каталоге с сервера на клиент.

Когда я запускаюмои текущие сценарии, я могу ввести имя файла для загрузки, но он не загружается и сразу переходит к следующей функции (для загрузки файла). Если я укажу файл для загрузки, он застрянет.

Я предполагаю, что моя проблема заключается в том, что сокеты принимают и закрывают сокет после выполнения действия, но я не уверен, как это сделать. ,Я включил код моего сервера и клиента ниже. Имейте в виду, что создание сокетов, привязка и прослушивание работают правильно.

client.c

/* A simple echo client using TCP */
#include <stdio.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <strings.h>


#define SERVER_TCP_PORT 3000    /* well-known port */
#define BUFLEN 256  /* buffer length */
#define sendrecvflag 0
#define cipherKey 'S' 


// function to clear buffer 
void clearBuf(char* b) 
{ 
    int i; 
    for (i = 0; i < BUFLEN; i++) 
        b[i] = '\0'; 
} 

// function for decryption 
char Cipher(char ch) 
{ 
    return ch ^ cipherKey; 
} 

// function to receive file 
int recvFile(char* buf, int s) 
{ 
    int i; 
    char ch; 
    for (i = 0; i < s; i++) { 
        ch = buf[i]; 
        ch = Cipher(ch); 
        if (ch == EOF) 
            return 1; 
        else
            printf("%c", ch); 
    } 
    return 0; 
} 


int main(int argc, char **argv)
{
    int     n, i, bytes_to_read, b, nBytes;
    int     sockfd, port;
    struct  hostent     *hp;
    struct  sockaddr_in server;
    char    *host, *bp, net_buf[BUFLEN], input[20];
        int addrlen = sizeof(server);

    switch(argc){
    case 2:
        host = argv[1];
        port = SERVER_TCP_PORT;
        break;
    case 3:
        host = argv[1];
        port = atoi(argv[2]);
        break;
    default:
        fprintf(stderr, "Usage: %s host [port]\n", argv[0]);
        exit(1);
    }

    /* Create a stream socket   */  
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "Can't creat a socket\n");
        exit(1);
    }

    /* Bind an address to the socket    */
    bzero((char *)&server, sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    if (hp = gethostbyname(host)) 
      bcopy(hp->h_addr, (char *)&server.sin_addr, hp->h_length);
    else if ( inet_aton(host, (struct in_addr *) &server.sin_addr) ){
      fprintf(stderr, "Can't get server's address\n");
      exit(1);
    }

    /* Connecting to the server */
    if (connect(sockfd, (struct sockaddr *)&server, addrlen) == -1){
      fprintf(stderr, "Can't connect \n");
      exit(1);
    }

    while(1){

        //This is for file upload--------------
        printf("Specify file to upload:");
        scanf("%s", &input);

        //need to create this file in the file system.
        FILE *fp = fopen(input, "rb");

        if(fp == NULL){
            perror("File doesnt exist");
            return 2;
        }

        while( (b = fread(net_buf, 1, sizeof(net_buf), fp))>0 ){
            send(sockfd, net_buf, b, sendrecvflag);
        }
        printf("done sending content");
        fclose(fp);

        //This is for file download---------------
        printf("Specify the file that you want to download from server:");
        scanf("%s", net_buf);

        sendto(sockfd, net_buf, BUFLEN, 
                sendrecvflag, (struct sockaddr*)&server, 
                addrlen);

        printf("\n---------Data Received---------\n"); 
        while(1){
            // receive 
                clearBuf(net_buf); 

                nBytes = recvfrom(sockfd, net_buf, BUFLEN, 
                        sendrecvflag, (struct sockaddr*)&server,
                        &addrlen);


                // process 
                if (recvFile(net_buf, BUFLEN)) { 
                    break; 
                } 
        }

        //This is for Change in directory
        printf("Specify the directory you want to change to: ");
        scanf("%s", net_buf);
        sendto(sockfd, net_buf, BUFLEN, 
               sendrecvflag, (struct sockaddr*)&server, 
               addrlen);

        printf("\n---------Directory Has been Changed---------\n"); 


        //This is for Listing directory
        printf("Specify the directory(ex.'.'): ");
        scanf("%s", net_buf);

        sendto(sockfd, net_buf, BUFLEN, 
               sendrecvflag, (struct sockaddr*)&server, 
               addrlen);

        printf("\n---------Directory Data Received---------\n"); 

        while(1){
            // receive 
                clearBuf(net_buf); 

                nBytes = recvfrom(sockfd, net_buf, BUFLEN, 
                                    sendrecvflag, (struct sockaddr*)&server,
                                    &addrlen);


                // process 
                if (recvFile(net_buf, BUFLEN)) { 
                    break; 
                } 
        }
        //End
    }
    close(sockfd);
    return(0);
}

server.c

/* A simple echo server using TCP */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <dirent.h>
#include <string.h>

#define SERVER_TCP_PORT 3000    /* well-known port */
#define BUFLEN 256  /* buffer length */
#define cipherKey 'S' 
#define nofile "File Not Found!" 
#define sendrecvflag 0

int echod(int);
void reaper(int);


// function to clear buffer 
void clearBuf(char* b) 
{ 
    int i; 
    for (i = 0; i < BUFLEN; i++) 
        b[i] = '\0'; 
} 


// function for decryption 
char Cipher(char ch) 
{ 
    return ch ^ cipherKey; 
} 


// function sending file 
int sendFile(FILE* fp, char* buf, int s) 
{ 
    int i, len; 
    if (fp == NULL) { 
        strcpy(buf, nofile); 
        len = strlen(nofile); 
        buf[len] = EOF; 
        for (i = 0; i <= len; i++) 
            buf[i] = Cipher(buf[i]); 
        return 1; 
    } 

    char ch, ch2; 
    for (i = 0; i < s; i++) { 
        ch = fgetc(fp); 
        ch2 = Cipher(ch); 
        buf[i] = ch2; 
        if (ch == EOF) 
            return 1; 
    } 
    return 0; 
} 


int main(int argc, char **argv)
{
    int     sockfd, new_sd, client_len, port, confd = 0,b,tot, nBytes;
    struct  sockaddr_in server, client;
    char net_buf[BUFLEN];
    int addrlen = sizeof(server);

    switch(argc){
    case 1:
        port = SERVER_TCP_PORT;
        break;
    case 2:
        port = atoi(argv[1]);
        break;
    default:
        fprintf(stderr, "Usage: %d [port]\n", argv[0]);
        exit(1);
    }

    /* Create a stream socket   */  
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        fprintf(stderr, "Can't creat a socket\n");
        exit(1);
    }

    /* Bind an address to the socket    */
    bzero((char *)&server, sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sockfd, (struct sockaddr *)&server, addrlen) == -1){
        fprintf(stderr, "Can't bind name to socket\n");
        exit(1);
    }


    if(listen(sockfd, 10) < 0) {
        perror("listen");
        exit(1);
    }



    while(1) {

      //This is for file upload
      printf("This is sending file");
      confd = accept(sockfd, (struct sockaddr*)NULL, NULL);
        if (confd==-1) {
            perror("Accept");
            continue;
        }
        //Should create a text file.
        FILE* fp = fopen( "test.txt", "wb");
        tot=0;

        if(fp != NULL){
            while( (b = recv(confd, net_buf, BUFLEN,sendrecvflag))> 0 ) {
                tot+=b;
                fwrite(net_buf, 1, b, fp);
            }

            printf("Received byte: %d\n",tot);
            if (b<0)
               perror("Error recieving the file");

            fclose(fp);
        } else {
            perror("File doesnt exist");
        }

    close(confd);

        //This is for file download
        printf("\nWaiting for file name...\n");
        confd = accept(sockfd, (struct sockaddr*)NULL, NULL);
        if (confd==-1){
        perror("Accept");
        continue;
        }

        // receive file name 
        clearBuf(net_buf); 

        nBytes = recvfrom(sockfd, net_buf, 
                          BUFLEN, sendrecvflag, 
                          (struct sockaddr *)&server, &addrlen);

        fp = fopen(net_buf, "r");

        printf("\nFile Name Received: %s\n", net_buf); 
        if (fp == NULL) 
            printf("\nFile open failed!\n"); 
        else
            printf("\nFile Successfully opened!\n"); 


        while (1) { 

            // process 
            if (sendFile(fp, net_buf, BUFLEN)) { 
                sendto(sockfd, net_buf, BUFLEN, 
                       sendrecvflag,  
                    (struct sockaddr*)&server, addrlen); 
                break; 
            } 

            // send 
            sendto(sockfd, net_buf, BUFLEN, 
                   sendrecvflag, 
                (struct sockaddr*)&server, addrlen); 
            clearBuf(net_buf); 
        } 
        if (fp != NULL) 
            fclose(fp); 

        //This is for Change in directory
        clearBuf(net_buf);
        nBytes = recvfrom(sockfd, net_buf, 
                          BUFLEN, sendrecvflag, 
                          (struct sockaddr*)&server, &addrlen);
        chdir(net_buf);


        //This is for Listing directory
        clearBuf(net_buf); 
        nBytes = recvfrom(sockfd, net_buf, 
                          BUFLEN, sendrecvflag, 
                          (struct sockaddr*)&server, &addrlen);
        DIR *d;
        struct dirent *dir;
        d = opendir(net_buf);
        if (d){
                while ((dir = readdir(d)) != NULL)
                {
                    // send 
                    strcpy(net_buf,dir->d_name );
                    sendto(sockfd, net_buf, BUFLEN, 
                        sendrecvflag, 
                        (struct sockaddr*)&server, addrlen); 
                    clearBuf(net_buf);
                }
                closedir(d);
        }else{
            printf("File Directory doesnt exist");
        }
        //End
    }
}

У меня есть функции, которыезашифровать и отправить данные в обоих. Это не обязательно, но я хотел понять шифрование на очень высоком уровне. Основной код начинается после первого цикла while. Там не так много кода. И последнее, что следует упомянуть, - это то, что IP и номер порта отправляются в качестве аргумента, опять же, это не то, что требует внимания, так как соединение установлено успешно.

...