Cliente e Servidor TFTP

O Trivial File Transfer Protocol (ou apenas TFTP) é um protocolo de transferência de arquivos, muito simples, semelhante ao FTP.

O TFTP é usualmente utilizado para transferir pequenos arquivos entre hosts numa rede. O TFPT trabalha com o protocolo de transporte UDP, o servidor TFTP recebe conexões na porta 69 e o tamanho de cada bloco é de 512 bytes.

Os exemplos abaixo trabalham na porta 2424 e o bloco tem tamanho de 1024 bytes.

Servidor TFTP simples

Recebe conexões (trata apenas 1 conexão por vez) e cria arquivo com permissão fixa. Neste Exemplo falta:

  • Enviar mensagem de erro em caso de problemas
  • Respeitar os atributos originais do arquivo
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <strings.h>
#include <arpa/inet.h>
#include <fcntl.h>
 
#define SIZE_BUFFER 1024
int main(void)
{
   int iSock, iFileDescriptor;
   struct sockaddr_in my_addr;
   struct sockaddr_in client_addr;
   socklen_t addr_len;
   int iNumBytes;
   char sBuffer[SIZE_BUFFER];
 
   if ((iSock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
      perror("socket");
      exit(1);
   }
 
   my_addr.sin_family = AF_INET;
   my_addr.sin_port = htons(2424);
   my_addr.sin_addr.s_addr = INADDR_ANY;
   bzero(&(my_addr.sin_zero), 8);
 
   if (bind(iSock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) < 0 )
   {
      perror("bind");
      exit(1);
   }
 
   /* loop infinito recebendo dados */
   while(1)
   {
      addr_len = sizeof(struct sockaddr);
      if ((iNumBytes=recvfrom(iSock, sBuffer, SIZE_BUFFER, 0, (struct sockaddr *)&client_addr, &addr_len)) < 0)
      {
         perror("recvfrom");
         exit(1);
      }
      fprintf(stderr, "Recebendo pacotes de %s\n",inet_ntoa(client_addr.sin_addr));
      fprintf(stderr, "o pacote tem %d bytes\n",iNumBytes);
      sBuffer[iNumBytes] = '\0';
      if( strcmp(sBuffer,"01INICIO") == 0 )
      {
         if ((iNumBytes=recvfrom(iSock, sBuffer, SIZE_BUFFER, 0, (struct sockaddr *)&client_addr, &addr_len)) < 0)
         {
            perror("recvfrom");
            exit(1);
         }
 
         sBuffer[iNumBytes] = '\0';
         fprintf(stderr, "\nRecebendo o arquivo %s", sBuffer);
         iFileDescriptor = creat(sBuffer, 0644 ); /* permissao -rw-r--r-- */
 
         if( iFileDescriptor < 0 )
         {
            perror("creat");
            exit(1);
         }
 
         /* até todo o arquivo chegar, fico lendo */
         iNumBytes=recvfrom(iSock, sBuffer, SIZE_BUFFER, 0, (struct sockaddr *)&client_addr, &addr_len);
         while( iNumBytes > 0)
         {
            sBuffer[iNumBytes] = '\0';
            if( strcmp(sBuffer, "01FIM") == 0) /* fim de transmissao */
            {
               break;
            }
            fprintf(stderr, "\nRecebendo ....... %d OK", iNumBytes);
            write( iFileDescriptor, sBuffer, iNumBytes);
            iNumBytes=recvfrom(iSock, sBuffer, SIZE_BUFFER, 0, (struct sockaddr *)&client_addr, &addr_len);
         }
         if( iNumBytes < 0 )
         {
            perror("recvfrom");
            exit(1);
         }
         close(iFileDescriptor);
         fprintf(stderr, "\nFim da transferencia");
      }
   }
   close(iSock);
 
   return 0;
}

Cliente TFTP Simples

Envia um arquivo a partir da linha comando. Neste exemplo falta:

  • Notificar servidor no caso de erro
  • Fazer autenticação junto ao servidor
  • Enviar múltiplos arquivos
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <strings.h>
#include <arpa/inet.h>
#include <fcntl.h>
 
#define SIZE_BUFFER 1024
 
int main(int argc, char *argv[])
{
   int iSock, iFileDescriptor, iNumBytes;
   struct sockaddr_in server_addr;
   struct hostent *he;
 
   char sBuffer[SIZE_BUFFER];
 
   if (argc != 3)
   {
      printf("Passe o nome do servidor e o nome do arquivo a ser enviado");
      exit(1);
   }
 
   /* convertendo o endereco passado para uma estrutura que eu entendo */
   if ((he=gethostbyname(argv[1])) == NULL)
   {
      perror("gethostbyname");
      exit(1);
   }
 
   if ((iSock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
   {
      perror("socket");
      exit(1);
   }
 
   /* abrir o arquivo passado */
   iFileDescriptor = open(argv[2],O_RDONLY);
   if( iFileDescriptor < 0 )
   {
      perror("open");
      exit(1);
   }
 
   server_addr.sin_family = AF_INET;
   server_addr.sin_port = htons(2424); /* em homenagem a voces... ;) */
 
   server_addr.sin_addr = *((struct in_addr *)he->h_addr);
   bzero(&(server_addr.sin_zero), 8);
 
   /* inicio do envio */
   iNumBytes = sendto(iSock, "01INICIO", 8, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
   if(iNumBytes < 0 )
   {
      perror("sendto");
      exit(1);
   }
   /* primeiro é enviado o nome do arquivo */
   iNumBytes = sendto(iSock, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
   if(iNumBytes < 0 )
   {
      perror("sendto");
      exit(1);
   }
 
   iNumBytes = read(iFileDescriptor, &sBuffer, SIZE_BUFFER ) ;
   while( iNumBytes > 0 )
   {
      /* enviando o buffer */
      iNumBytes = sendto(iSock, sBuffer, iNumBytes, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
      if(iNumBytes < 0 )
      {
         perror("sendto (2)");
         exit(1);
      }
      fprintf(stderr, "\nEnviando ......................... %d OK", iNumBytes);
      iNumBytes = read(iFileDescriptor, &sBuffer, SIZE_BUFFER ) ;
   }
 
   if( iNumBytes < 0 )
   {
      perror("read");
      exit(1);
   }
   /* fim do envio */
   iNumBytes = sendto(iSock, "01FIM", 5, 0, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
   if(iNumBytes < 0 )
   {
      perror("sendto");
      exit(1);
   }
 
   close(iSock);
   close(iFileDescriptor);
   return 0;
}

Marcos Laureano 2008/04/29 09:11

exemplo_tftp.txt · Última modificação: 2008/04/29 09:13 por laureano
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0