Application in C Client-server for file transfer with TCP socket and thread [closed]

3

I would like to ask the forum help to make safe (encrypt) the transfer of a file between two computers. Below is the C source code of a client-server application for file transfer using TCP socket but without encryption of the transferred data. Could you point me to literature or an example in C of how to encrypt the transferred data?

It is a simple project, intended for teaching purposes only. It includes Thread with sockets for connecting multiple clients. The server lists a directory that is passed as a parameter and the port that listens to allow connections to clients. The client passes the port, the IP address, and the name of the file you want to get from the server.

To compile the server code:

gcc -o server server.c -lpthread

To compile the client code:

gcc -o client client.c

Server C code:

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <ctype.h>
#include <pthread.h>

void *connection_handler(void *);

#define MAX_MSG 1024

/*
 Servidor aguarda por mensagem do cliente, imprime na tela
 e depois envia resposta e finaliza processo
 */

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

    //Variaveis auxiliares para encontrar o arquivo a ser transferido.
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;
    //verificando se foi executando o comando corretamente
    if (argc != 3) {
        fprintf(stderr, "use:./server [Porta] [local]\n");
        return -1;
    } else if (!isdigit(*argv[1])) {
        fprintf(stderr, "Argumento invalido '%s'\n", argv[1]);
        fprintf(stderr, "use:./server [Porta] [local]\n");
        return -1;
    }

    mydir = opendir(argv[2]);
    //verificando se o diretorio existe
    if(mydir == NULL ){fprintf(stderr, "Argumento invalido '%s'\n", argv[2]);return -1;}
    char* aux1 = argv[1];
        int portaServidor = atoi(aux1);

   //variaveis
    int socket_desc, conexao, c, nova_conex;
    struct sockaddr_in servidor, cliente;
    char *mensagem;
    char resposta[MAX_MSG];
    int tamanho, count;

    // para pegar o IP e porta do cliente  
    char *cliente_ip;
    int cliente_port;

    //*********************************************************************//
    //      INICIO DO TRATAMENTO DA THREAD, localização e transferencia    // 
    //      do arquivo.                                                    // 
    //*********************************************************************//
    void *connection_handler(void *socket_desc) {
        /*********************************************************/

        /*********comunicao entre cliente/servidor****************/

        // pegando IP e porta do cliente
        cliente_ip = inet_ntoa(cliente.sin_addr);
        cliente_port = ntohs(cliente.sin_port);
        printf("cliente conectou: %s : [ %d ]\n", cliente_ip, cliente_port);

        // lendo dados enviados pelo cliente
        //mensagem 1 recebido nome do arquivo   
        if ((tamanho = read(conexao, resposta, MAX_MSG)) < 0) {
            perror("Erro ao receber dados do cliente: ");
            return NULL;
        }
        resposta[tamanho] = '
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define MAX_MSG 1024

/*
 Cliente envia mensagem ao servidor e imprime resposta
 recebida do Servidor
 */

int main(int argc, char *argv[]) {
    FILE *received_file;
    received_file = fopen(argv[3], "w");
    ssize_t len;
    char buffer[BUFSIZ];
    int aba;

      if (argc != 4) {
        fprintf(stderr, "use:./cliente [IP] [Porta] [arquivo]\n");
        return -1;
    } else if (!isdigit(*argv[2])) {
        fprintf(stderr, "Argumento invalido '%s'\n", argv[2]);
        fprintf(stderr, "use:./cliente [IP] [Porta] [arquivo]\n");
        return -1;
    }

    // variaveis
    int socket_desc;
    struct sockaddr_in servidor;
    char *mensagem;
    char resposta_servidor[MAX_MSG];
    int tamanho;
    mensagem = argv[3];
    char* aux1 = argv[2];
    int portaServidor = atoi(aux1);

    /*****************************************/
    /* Criando um socket */
    // AF_INET = ARPA INTERNET PROTOCOLS
    // SOCK_STREAM = orientado a conexao
    // 0 = protocolo padrao para o tipo escolhido -- TCP
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc == -1) {
        printf("Nao foi possivel criar socket\n");
        return -1;
    }

    /* Informacoes para conectar no servidor */
    // IP do servidor
    // familia ARPANET
    // Porta - hton = host to network short (2bytes)
    servidor.sin_addr.s_addr = inet_addr(argv[1]);
    servidor.sin_family = AF_INET;
    servidor.sin_port = htons(portaServidor);

    //Conectando no servidor remoto
    if (connect(socket_desc, (struct sockaddr *) &servidor, sizeof (servidor)) < 0) {
        printf("Nao foi possivel conectar\n");
        return -1;
    }
    printf("Conectado no servidor\n");
    /*****************************************/


    /*******COMUNICAO - TROCA DE MENSAGENS **************/

    //Enviando uma mensagem
    //mensagem 1 enviando nome do arquivo.  
    if (send(socket_desc, mensagem, strlen(mensagem), 0) < 0) {
        printf("Erro ao enviar mensagem\n");
        return -1;
    }
    printf("Dados enviados\n");

    memset(mensagem, 0, sizeof mensagem);
    memset(resposta_servidor, 0, sizeof resposta_servidor);

    //Recebendo resposta do servidor
    //mensagem 2 recebendo que arquivo existe   
    if((tamanho = read(socket_desc, resposta_servidor, MAX_MSG)) < 0) {
        printf("Falha ao receber resposta\n");
        return -1;
    }

    printf("Resposta recebida: %s\n", resposta_servidor);
    if (strcmp(resposta_servidor, "200") == 0) {

        mensagem = "OK";
        //mensagem 3 enviado ok
        write(socket_desc, mensagem, strlen(mensagem));
        //mensagem 4 recebendo o tamanho do arquivo;
        memset(resposta_servidor, 0, sizeof resposta_servidor);
        read(socket_desc, resposta_servidor, 1024);

        int tamanhoDoArquivo = atoi(resposta_servidor);
        printf("\nTamanho do arquivo a ser copiado: %s \n", resposta_servidor);
        aba = tamanhoDoArquivo;

    }else{
        fprintf(stderr, "Arquivo nao encontrado no servirdor'%s'\n", argv[3]);
        close(socket_desc);
        printf("Cliente finalizado com sucesso!\n");
        return 0;
    }

    while (((len = recv(socket_desc, buffer, BUFSIZ, 0)) > 0)&& (aba > 0)) {
        fwrite(buffer, sizeof (char), len, received_file);
        aba -= len;
        fprintf(stdout, "Recebidos %d bytes e aguardamos :- %d bytes\n", len, aba);
        if (aba <= 0) {
            break;
        }
    }
    fclose(received_file);
    close(socket_desc);

    printf("Cliente finalizado com sucesso!\n");
    return 0;
}
'; printf("O cliente falou: %s\n", resposta); char aux_nomeArquivo[MAX_MSG]; //fazendo cópia do nome do arquivo para variável auxiliar. tal variavel é utilzada para localizar // o arquivo no diretorio. strncpy(aux_nomeArquivo, resposta, MAX_MSG); //printf("ax_nomeArquivo: %s\n", aux_nomeArquivo); /*********************************************************/ if (mydir != NULL) { //função busca todo o diretório buscando o arquivo na variavel aux_nomeArquivo //struct stat s; while ((myfile = readdir(mydir)) != NULL) { stat(myfile->d_name, &mystat); printf("Arquivo lido: %s, Arquivo procurado: %s\n", myfile->d_name, resposta); if (strcmp(myfile->d_name, resposta) == 0) {//arquivo existe closedir(mydir); //Reiniciando variáveis da pesquisa do diretorio para a proxima thread myfile = NULL; mydir = NULL; mydir = opendir(argv[2]); //**************************************// // INICIO DO PROTOCOLO // //*************************************// mensagem = "200"; //mensagem 2 - enviando confirmação q arquivo existe write(conexao, mensagem, strlen(mensagem)); //mensagem 3 - recebendo que arquivo OK do cliente read(conexao, resposta, MAX_MSG); //**************************************// // FIM DO PROTOCOLO // //*************************************// //abrindo o arquivo e retirando o tamanho// //fazendo cópia do nome do arquivo para variável auxiliar. tal variavel é utilzada para localizar // o arquivo no diretorio. char localArquivo[1024]; strncpy(localArquivo, argv[2], 1024); strcat(localArquivo,aux_nomeArquivo); FILE * f = fopen(localArquivo, "rb"); if((fseek(f, 0, SEEK_END))<0){printf("ERRO DURANTE fseek");} int len = (int) ftell(f); mensagem = (char*) len; printf("Tamanho do arquivo: %d\n", len); //convertendo o valor do tamanho do arquivo (int) para ser enviado em uma mensagem no scoket(char) char *p, text[32]; int a = len; sprintf(text, "%d", len); mensagem = text; //mensagem 4 - enviando o tamanho do arquivo send(conexao, mensagem, strlen(mensagem), 0); int fd = open(localArquivo, O_RDONLY); off_t offset = 0; int sent_bytes = 0; //localArquivo = NULL; if (fd == -1) { fprintf(stderr, "Error opening file --> %s", strerror(errno)); exit(EXIT_FAILURE); } while (((sent_bytes = sendfile(conexao, fd, &offset, BUFSIZ)) > 0)&& (len > 0)) { fprintf(stdout, "1. Servidor enviou %d bytes do arquivo, offset é agora : %d e os dados restantes = %d\n", sent_bytes, (int)offset, len); len -= sent_bytes; fprintf(stdout, "2.Servidor enviou %d bytes do arquivo, offset é agora : %d e os dados restantes = %d\n", sent_bytes, (int)offset, len); if (len <= 0) { break; } } //closedir(mydir); while (1) { } } }if(myfile==NULL) { //enviando mensagem para o cliente de arquivo nao encontrado. mensagem = "404";//file not found printf("\n//*********************************//\n"); printf("Arquivo \"%s\" Não Existe no diretório: \"%s\"\n",aux_nomeArquivo, argv[2]); //mensagem 2 - enviando confirmação q arquivo existe write(conexao, mensagem, strlen(mensagem)); //sempre que termina de pesquisar o diretorio de arquivos a variavel myfile vai para null // entao eh necessario preencher mydir novamente com o argv[2] com o diretorio de pesquisa. //caso contrario novas thread nao acessaram o diretorio passado em argv[2]] mydir = opendir(argv[2]); // while (1) { } close(conexao); //closedir(mydir); } if (mydir != NULL) { closedir(mydir); mydir = NULL; } } if (strcmp(resposta, "bye\n") == 0) { close(conexao); printf("Servidor finalizado...\n"); return NULL; } } //*********************************************************************// // FIM DO TRATAMENTO DA THREAD, localização e transferencia // // do arquivo. // //*********************************************************************// //************************************************************ /*********************************************************/ //Criando um socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Nao foi possivel criar o socket\n"); return -1; } //Preparando a struct do socket servidor.sin_family = AF_INET; servidor.sin_addr.s_addr = INADDR_ANY; // Obtem IP do S.O. servidor.sin_port = htons(portaServidor); //Associando o socket a porta e endereco if (bind(socket_desc, (struct sockaddr *) &servidor, sizeof (servidor)) < 0) { puts("Erro ao fazer bind Tente outra porta\n"); return -1; } puts("Bind efetuado com sucesso\n"); // Ouvindo por conexoes listen(socket_desc, 3); /*********************************************************/ //Aceitando e tratando conexoes puts("Aguardando por conexoes..."); c = sizeof (struct sockaddr_in); while ((conexao = accept(socket_desc, (struct sockaddr *) &cliente, (socklen_t*) & c))) { if (conexao < 0) { perror("Erro ao receber conexao\n"); return -1; } pthread_t sniffer_thread; nova_conex = (int) malloc(1); nova_conex = conexao; if (pthread_create(&sniffer_thread, NULL, connection_handler, (void*) nova_conex) < 0) { perror("could not create thread"); return 1; } puts("Handler assigned"); } if (nova_conex < 0) { perror("accept failed"); return 1; } }

Client C code:

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/sendfile.h>
#include <ctype.h>
#include <pthread.h>

void *connection_handler(void *);

#define MAX_MSG 1024

/*
 Servidor aguarda por mensagem do cliente, imprime na tela
 e depois envia resposta e finaliza processo
 */

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

    //Variaveis auxiliares para encontrar o arquivo a ser transferido.
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;
    //verificando se foi executando o comando corretamente
    if (argc != 3) {
        fprintf(stderr, "use:./server [Porta] [local]\n");
        return -1;
    } else if (!isdigit(*argv[1])) {
        fprintf(stderr, "Argumento invalido '%s'\n", argv[1]);
        fprintf(stderr, "use:./server [Porta] [local]\n");
        return -1;
    }

    mydir = opendir(argv[2]);
    //verificando se o diretorio existe
    if(mydir == NULL ){fprintf(stderr, "Argumento invalido '%s'\n", argv[2]);return -1;}
    char* aux1 = argv[1];
        int portaServidor = atoi(aux1);

   //variaveis
    int socket_desc, conexao, c, nova_conex;
    struct sockaddr_in servidor, cliente;
    char *mensagem;
    char resposta[MAX_MSG];
    int tamanho, count;

    // para pegar o IP e porta do cliente  
    char *cliente_ip;
    int cliente_port;

    //*********************************************************************//
    //      INICIO DO TRATAMENTO DA THREAD, localização e transferencia    // 
    //      do arquivo.                                                    // 
    //*********************************************************************//
    void *connection_handler(void *socket_desc) {
        /*********************************************************/

        /*********comunicao entre cliente/servidor****************/

        // pegando IP e porta do cliente
        cliente_ip = inet_ntoa(cliente.sin_addr);
        cliente_port = ntohs(cliente.sin_port);
        printf("cliente conectou: %s : [ %d ]\n", cliente_ip, cliente_port);

        // lendo dados enviados pelo cliente
        //mensagem 1 recebido nome do arquivo   
        if ((tamanho = read(conexao, resposta, MAX_MSG)) < 0) {
            perror("Erro ao receber dados do cliente: ");
            return NULL;
        }
        resposta[tamanho] = '
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define MAX_MSG 1024

/*
 Cliente envia mensagem ao servidor e imprime resposta
 recebida do Servidor
 */

int main(int argc, char *argv[]) {
    FILE *received_file;
    received_file = fopen(argv[3], "w");
    ssize_t len;
    char buffer[BUFSIZ];
    int aba;

      if (argc != 4) {
        fprintf(stderr, "use:./cliente [IP] [Porta] [arquivo]\n");
        return -1;
    } else if (!isdigit(*argv[2])) {
        fprintf(stderr, "Argumento invalido '%s'\n", argv[2]);
        fprintf(stderr, "use:./cliente [IP] [Porta] [arquivo]\n");
        return -1;
    }

    // variaveis
    int socket_desc;
    struct sockaddr_in servidor;
    char *mensagem;
    char resposta_servidor[MAX_MSG];
    int tamanho;
    mensagem = argv[3];
    char* aux1 = argv[2];
    int portaServidor = atoi(aux1);

    /*****************************************/
    /* Criando um socket */
    // AF_INET = ARPA INTERNET PROTOCOLS
    // SOCK_STREAM = orientado a conexao
    // 0 = protocolo padrao para o tipo escolhido -- TCP
    socket_desc = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_desc == -1) {
        printf("Nao foi possivel criar socket\n");
        return -1;
    }

    /* Informacoes para conectar no servidor */
    // IP do servidor
    // familia ARPANET
    // Porta - hton = host to network short (2bytes)
    servidor.sin_addr.s_addr = inet_addr(argv[1]);
    servidor.sin_family = AF_INET;
    servidor.sin_port = htons(portaServidor);

    //Conectando no servidor remoto
    if (connect(socket_desc, (struct sockaddr *) &servidor, sizeof (servidor)) < 0) {
        printf("Nao foi possivel conectar\n");
        return -1;
    }
    printf("Conectado no servidor\n");
    /*****************************************/


    /*******COMUNICAO - TROCA DE MENSAGENS **************/

    //Enviando uma mensagem
    //mensagem 1 enviando nome do arquivo.  
    if (send(socket_desc, mensagem, strlen(mensagem), 0) < 0) {
        printf("Erro ao enviar mensagem\n");
        return -1;
    }
    printf("Dados enviados\n");

    memset(mensagem, 0, sizeof mensagem);
    memset(resposta_servidor, 0, sizeof resposta_servidor);

    //Recebendo resposta do servidor
    //mensagem 2 recebendo que arquivo existe   
    if((tamanho = read(socket_desc, resposta_servidor, MAX_MSG)) < 0) {
        printf("Falha ao receber resposta\n");
        return -1;
    }

    printf("Resposta recebida: %s\n", resposta_servidor);
    if (strcmp(resposta_servidor, "200") == 0) {

        mensagem = "OK";
        //mensagem 3 enviado ok
        write(socket_desc, mensagem, strlen(mensagem));
        //mensagem 4 recebendo o tamanho do arquivo;
        memset(resposta_servidor, 0, sizeof resposta_servidor);
        read(socket_desc, resposta_servidor, 1024);

        int tamanhoDoArquivo = atoi(resposta_servidor);
        printf("\nTamanho do arquivo a ser copiado: %s \n", resposta_servidor);
        aba = tamanhoDoArquivo;

    }else{
        fprintf(stderr, "Arquivo nao encontrado no servirdor'%s'\n", argv[3]);
        close(socket_desc);
        printf("Cliente finalizado com sucesso!\n");
        return 0;
    }

    while (((len = recv(socket_desc, buffer, BUFSIZ, 0)) > 0)&& (aba > 0)) {
        fwrite(buffer, sizeof (char), len, received_file);
        aba -= len;
        fprintf(stdout, "Recebidos %d bytes e aguardamos :- %d bytes\n", len, aba);
        if (aba <= 0) {
            break;
        }
    }
    fclose(received_file);
    close(socket_desc);

    printf("Cliente finalizado com sucesso!\n");
    return 0;
}
'; printf("O cliente falou: %s\n", resposta); char aux_nomeArquivo[MAX_MSG]; //fazendo cópia do nome do arquivo para variável auxiliar. tal variavel é utilzada para localizar // o arquivo no diretorio. strncpy(aux_nomeArquivo, resposta, MAX_MSG); //printf("ax_nomeArquivo: %s\n", aux_nomeArquivo); /*********************************************************/ if (mydir != NULL) { //função busca todo o diretório buscando o arquivo na variavel aux_nomeArquivo //struct stat s; while ((myfile = readdir(mydir)) != NULL) { stat(myfile->d_name, &mystat); printf("Arquivo lido: %s, Arquivo procurado: %s\n", myfile->d_name, resposta); if (strcmp(myfile->d_name, resposta) == 0) {//arquivo existe closedir(mydir); //Reiniciando variáveis da pesquisa do diretorio para a proxima thread myfile = NULL; mydir = NULL; mydir = opendir(argv[2]); //**************************************// // INICIO DO PROTOCOLO // //*************************************// mensagem = "200"; //mensagem 2 - enviando confirmação q arquivo existe write(conexao, mensagem, strlen(mensagem)); //mensagem 3 - recebendo que arquivo OK do cliente read(conexao, resposta, MAX_MSG); //**************************************// // FIM DO PROTOCOLO // //*************************************// //abrindo o arquivo e retirando o tamanho// //fazendo cópia do nome do arquivo para variável auxiliar. tal variavel é utilzada para localizar // o arquivo no diretorio. char localArquivo[1024]; strncpy(localArquivo, argv[2], 1024); strcat(localArquivo,aux_nomeArquivo); FILE * f = fopen(localArquivo, "rb"); if((fseek(f, 0, SEEK_END))<0){printf("ERRO DURANTE fseek");} int len = (int) ftell(f); mensagem = (char*) len; printf("Tamanho do arquivo: %d\n", len); //convertendo o valor do tamanho do arquivo (int) para ser enviado em uma mensagem no scoket(char) char *p, text[32]; int a = len; sprintf(text, "%d", len); mensagem = text; //mensagem 4 - enviando o tamanho do arquivo send(conexao, mensagem, strlen(mensagem), 0); int fd = open(localArquivo, O_RDONLY); off_t offset = 0; int sent_bytes = 0; //localArquivo = NULL; if (fd == -1) { fprintf(stderr, "Error opening file --> %s", strerror(errno)); exit(EXIT_FAILURE); } while (((sent_bytes = sendfile(conexao, fd, &offset, BUFSIZ)) > 0)&& (len > 0)) { fprintf(stdout, "1. Servidor enviou %d bytes do arquivo, offset é agora : %d e os dados restantes = %d\n", sent_bytes, (int)offset, len); len -= sent_bytes; fprintf(stdout, "2.Servidor enviou %d bytes do arquivo, offset é agora : %d e os dados restantes = %d\n", sent_bytes, (int)offset, len); if (len <= 0) { break; } } //closedir(mydir); while (1) { } } }if(myfile==NULL) { //enviando mensagem para o cliente de arquivo nao encontrado. mensagem = "404";//file not found printf("\n//*********************************//\n"); printf("Arquivo \"%s\" Não Existe no diretório: \"%s\"\n",aux_nomeArquivo, argv[2]); //mensagem 2 - enviando confirmação q arquivo existe write(conexao, mensagem, strlen(mensagem)); //sempre que termina de pesquisar o diretorio de arquivos a variavel myfile vai para null // entao eh necessario preencher mydir novamente com o argv[2] com o diretorio de pesquisa. //caso contrario novas thread nao acessaram o diretorio passado em argv[2]] mydir = opendir(argv[2]); // while (1) { } close(conexao); //closedir(mydir); } if (mydir != NULL) { closedir(mydir); mydir = NULL; } } if (strcmp(resposta, "bye\n") == 0) { close(conexao); printf("Servidor finalizado...\n"); return NULL; } } //*********************************************************************// // FIM DO TRATAMENTO DA THREAD, localização e transferencia // // do arquivo. // //*********************************************************************// //************************************************************ /*********************************************************/ //Criando um socket socket_desc = socket(AF_INET, SOCK_STREAM, 0); if (socket_desc == -1) { printf("Nao foi possivel criar o socket\n"); return -1; } //Preparando a struct do socket servidor.sin_family = AF_INET; servidor.sin_addr.s_addr = INADDR_ANY; // Obtem IP do S.O. servidor.sin_port = htons(portaServidor); //Associando o socket a porta e endereco if (bind(socket_desc, (struct sockaddr *) &servidor, sizeof (servidor)) < 0) { puts("Erro ao fazer bind Tente outra porta\n"); return -1; } puts("Bind efetuado com sucesso\n"); // Ouvindo por conexoes listen(socket_desc, 3); /*********************************************************/ //Aceitando e tratando conexoes puts("Aguardando por conexoes..."); c = sizeof (struct sockaddr_in); while ((conexao = accept(socket_desc, (struct sockaddr *) &cliente, (socklen_t*) & c))) { if (conexao < 0) { perror("Erro ao receber conexao\n"); return -1; } pthread_t sniffer_thread; nova_conex = (int) malloc(1); nova_conex = conexao; if (pthread_create(&sniffer_thread, NULL, connection_handler, (void*) nova_conex) < 0) { perror("could not create thread"); return 1; } puts("Handler assigned"); } if (nova_conex < 0) { perror("accept failed"); return 1; } }

Thanks Stackoverflow.

    
asked by anonymous 25.11.2015 / 20:14

0 answers