Hi,

I'm making a windows port of some tftp client / server code from here

I've got the server working sucessfully with a diffrent client, however I have come to an impasse with the client code.
As I keep getting a server unreachable error, having tried over my local network and over localhost
Both the server and client for the most part share the same code, so my best guess is its an issue with hostent
or a windows specific header I have missed out.
since the server uses tftphdr instead of hostent.

any help will be appreciated thanks.

client.cpp

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <string.h>
#include <process.h>
#include <memory.h>
#include "tftp.h"

int TimeOut,NumberTimeOut,PortTFTP;
int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address); 

void tftp_connection(struct sockaddr_in *address,char *name)
{
    FILE *f;
    int r=255;

    f=fopen(name,"rb");
    r=tftp_send(address,name,"octet",1,TFTPsread,f);
    fclose(f);

    if (r!=0) printf("error tftp.\n\n");
};

using namespace std;

int main(int argc,char **argv)
{
    struct hostent *hp;          /* assigned to the server addres  */
    struct sockaddr_in server_connection;

    TimeOut=7; //time out length
    NumberTimeOut=3; // number of time outs

    if (argc<2)     {
        fprintf(stderr,"Usage: client.exe <server_name or ip address> <port> <file_name>\n\n"
                "All transfers are binary. If the file already exists, it will be replaced.\n\n");
        exit(2);
    };

    //server address aquisition from the first argv
    if ((hp=gethostbyname(argv[1]))==NULL)     {
        fprintf(stderr,"server %s is unreachable.\n",argv[1]);
        exit(2);
    }

    else
    {
    printf("Server has sucessfully been reached\n");
    }

    PortTFTP=atol(argv[2]); //port definition matching command line argument
    if (PortTFTP==0)
    {
        fprintf(stderr,"invalid port number.\n");
        exit(3);
    };

    server_connection.sin_family=AF_INET;
    server_connection.sin_port=htons(PortTFTP);
    memcpy(&server_connection.sin_addr.s_addr, hp->h_addr, hp->h_length); 
    tftp_connection(&server_connection,argv[3]); //argv[3] is the file to be transfered
    return 0;
};

tftp.h

#ifndef __TFTP_H
#define __TFTP_H 1
/*
 *custom declaration
 */
#pragma   pack(1)


typedef unsigned long       DWORD;
typedef int                 BOOL;
typedef unsigned char       BYTE;
typedef unsigned short      WORD;
/*
 * Trivial File Transfer Protocol (IEN-133)
 */
#define SEGSIZE 512         /* data segment size */
#define PKTSIZE SEGSIZE+4   /* full packet size */

/*
 * Packet types.
 */
#define RRQ 1               /* read request */
#define WRQ 2               /* write request */
#define DATA 3              /* data packet */
#define ACK 4               /* acknowledgement */
#define ERROR 5             /* error code */

struct  tftphdr {
    short   th_opcode;          /* packet type */
    union {
        unsigned short  tu_block;   /* block # */
        short   tu_code;        /* error code */
        char    tu_stuff[1];        /* request packet stuff */
    } th_u;
    char    th_data[1];         /* data or error string */
} ;

#define th_block    th_u.tu_block
#define th_code     th_u.tu_code
#define th_stuff    th_u.tu_stuff
#define th_msg      th_data

int tftp_receive(struct sockaddr_in *to, char *name, char *mode, int InClient,
                char (*TFTPwrite)(char *,long ,char,void *),
                void *argu);
int tftp_receive_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
                     char (*TFTPwrite)(char *,long ,char,void *),
                     void *argu,int vPKTSIZE);
int tftp_send(struct sockaddr_in *to,char *name,char *mode,int InClient,
              char (*TFTPread)(char *,long *,char,void *),
              void *argu);
int tftp_send_ext(struct sockaddr_in *to,char *name,char *mode,int InClient,
                  char (*TFTPread)(char *,long *,char,void *),
                  void *argu,int vPKTSIZE);

char TFTPswrite(char *data,long n,char first,void *f);
  // return 0 if no error.
char TFTPsread(char *data,long *n,char first,void *f);
  // return 0 if no error.

int tftp_send_buffer(struct sockaddr_in *to,char *name,char *mode,char *datas,DWORD l);

/*
 * Error codes.
 */
#define EUNDEF      0       /* not defined */
#define ENOTFOUND   1       /* file not found */
#define EACCESS     2       /* access violation */
#define ENOSPACE    3       /* disk full or allocation exceeded */
#define EBADOP      4       /* illegal TFTP operation */
#define EBADID      5       /* unknown transfer ID */
#define EEXISTS     6       /* file already exists */
#define ENOUSER     7       /* no such user */

#endif /* tftp.h */
`


tftp.cpp

 `
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include "tftp.h"

#pragma   comment(lib,   "ws2_32.lib")

extern int TimeOut,NumberTimeOut; 

#ifdef __sun__
#define FIONREAD I_NREAD
#endif

#define MIN(a,b) ((a)<(b)?(a):(b))

char TFTPswrite(char *data,long n,char first,void *f) 
{

    fwrite(data,n,1,(FILE *)f);
    return 0;
}

char TFTPsread(char *data,long *n,char first,void *f)
{
    *n=fread(data,1,SEGSIZE,(FILE *)f);
    return 0;
}

typedef struct TFTParg_buffer_tag 
{

    char *dat;
    long l;
} TFTParg_buffer;

char TFTPsSendBuffer(char *data,long *s,char first,void *a)
{
    long size=MIN(PKTSIZE-4,((TFTParg_buffer *)a)->l); 
    *s=size;
    memcpy(data,((TFTParg_buffer *)a)->dat,size);
    ((TFTParg_buffer *)a)->l-=size; ((TFTParg_buffer *)a)->dat+=size;
    return 0;
}

extern int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address);

int tftp_receive_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
                     char (*TFTPwrite)(char *,long ,char,void *),
                     void *argu,int vPKTSIZE)
{
    char *buf,*ackbuf,*dat,*cp; 
    tftphdr *dp,*ap;
    int i,size,n,ntimeout;
    SOCKET dataSocket; 
    struct timeval tv;
    u_short nextBlockNumber; 
    fd_set lecture;
    struct sockaddr_in from,to=*to1;
    size_t fromlen=sizeof(from),tolen=fromlen;

    buf=(char*)malloc(vPKTSIZE); 
    if (buf==NULL)
    {
        fprintf(stderr,"TFTP: out of memory.\n"); 
        return 255;
    }
    ackbuf=(char*)malloc(vPKTSIZE);  
    if (ackbuf==NULL)
    {
        fprintf(stderr,"TFTP: out of memory.\n");
        free(buf);
        return 255;
    }
    dp=(tftphdr *)buf;
    ap=(tftphdr *)ackbuf;
    dat=(char*)&dp->th_data[0];
    cp=(char*)&ap->th_stuff[0];

    i=0;
    if ((dataSocket=create_socket(SOCK_DGRAM, &i, NULL))<0)
    {
        free(buf); 
        free(ackbuf);
        return 255;
    }

    if (InClient)
    {
        ap->th_opcode=htons((u_short)RRQ); 
        strcpy(cp, name); 
        cp += strlen(name);
        *cp++ = '\0';
        strcpy(cp, mode);
        cp += strlen(mode);
        *cp++ = '\0';
        size=(DWORD)cp-(DWORD)ackbuf;
    }
    else
    {
        ap->th_opcode=htons((u_short)ACK);  
        ap->th_block=0;
        size=4;
    }
    nextBlockNumber=1;

    do
    {
      ntimeout=0;
      do
      {
         if (ntimeout==NumberTimeOut) 
         {
             closesocket(dataSocket);
             free(buf);
             free(ackbuf);
             return 255;
         }

         if (sendto(dataSocket,(const char*)ap,size,0,(struct sockaddr *)&to,tolen)!=size)
         {
             closesocket(dataSocket);
             free(buf);
             free(ackbuf);
             return 255;
         }

         do
         {
             n=-1;
             FD_ZERO(&lecture);
             FD_SET(dataSocket,&lecture);
             tv.tv_sec=TimeOut; tv.tv_usec=0;
             if ((i=select(dataSocket+1, &lecture, NULL, NULL, &tv))==-1)
             {
                closesocket(dataSocket);
                free(buf);
                free(ackbuf);
                return 255;
             }
             if (i>0)
                n=recvfrom(dataSocket, (char *)dp, vPKTSIZE, 0,(struct sockaddr *)&from, (int *)&fromlen);
         } while ((n<0)&&(i>0));

         if (i>0)
         {
            to.sin_port=from.sin_port;
            dp->th_opcode = ntohs((u_short)dp->th_opcode);
            dp->th_block = ntohs((u_short)dp->th_block);
            if (dp->th_opcode != DATA)
            {
                closesocket(dataSocket);
                free(buf);
                free(ackbuf);
                return 255;
            }

            if (dp->th_block != nextBlockNumber)
            {
               /* Re-synchronize with the other side */
               ioctlsocket(dataSocket, FIONREAD, (u_long *)&i); //i=number of byte in read-buffer
               while (i)
               {
                  recv(dataSocket, (char *)dp, vPKTSIZE, 0);
                  ioctlsocket(dataSocket, FIONREAD, (u_long *)&i);
               }
               dp->th_block=nextBlockNumber+1;
            }
         }
         ntimeout++;
      } while (dp->th_block!=nextBlockNumber);

      ap->th_block=htons(nextBlockNumber);
      nextBlockNumber++;

      if (nextBlockNumber==2)
      {
          ap->th_opcode=htons((u_short)ACK);
          size=4;
      }


      if ( (n-4) > 0 )
      {
          if (nextBlockNumber==2) i=(*TFTPwrite)(dat,n-4,1,argu);
          else i=(*TFTPwrite)(dat,n-4,0,argu);
          if (i)
          {
               closesocket(dataSocket);
               free(buf);
               free(ackbuf);
               return i;
          }
      }

   } while (n == vPKTSIZE);

   /* send the "final" aknowledgement */
   sendto(dataSocket, (const char *)ap, 4, 0,(struct sockaddr *)&to,tolen);
   closesocket(dataSocket);
   free(buf);
   free(ackbuf);
   return 0;
};

int tftp_receive(struct sockaddr_in *to1,char *name,char *mode,int InClient,
                 char (*TFTPwrite)(char *,long ,char,void *),
                 void *argu)
{
    return tftp_receive_ext(to1,name,mode,InClient,TFTPwrite,argu,PKTSIZE);
}

int tftp_send_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
                  char (*TFTPread)(char *,long *,char,void *),
                  void *argu, int vPKTSIZE)
{
    char *buf,*ackbuf,*dat,*cp;
    tftphdr *dp,*ap;
    int i,size,Oldsize=vPKTSIZE,n,ntimeout,dataSocket;
    unsigned short nextBlockNumber;
    struct timeval tv;
    fd_set lecture;
    struct sockaddr_in from,to=*to1;
    size_t fromlen=sizeof(from),tolen=fromlen;

    buf=(char*)malloc(vPKTSIZE);
    if (buf==NULL)
    {
        fprintf(stderr,"TFTP: out of memory.\n");
        return 255;
    }
    ackbuf=(char*)malloc(vPKTSIZE);
    if (ackbuf==NULL)
    {
        fprintf(stderr,"TFTP: out of memory.\n");
        free(buf); return 255;
    }
    dp=(tftphdr *)buf;
    ap=(tftphdr *)ackbuf;
    dat=(char*)&dp->th_data[0];
    cp=(char*)&dp->th_stuff[0];

    i=0;
    if ((dataSocket=create_socket(SOCK_DGRAM, &i, NULL))<0)
    {
        free(buf);
        free(ackbuf);
        return 255;
    }

    if (InClient)
    {
        dp->th_opcode=htons((u_short)WRQ);
        strcpy(cp, name);
        cp += strlen(name);
        *cp++ = '\0';
        strcpy(cp, mode);
        cp += strlen(mode);
        *cp++ = '\0';
        size=(DWORD)cp-(DWORD)buf;
        nextBlockNumber=0;
    }
    else
    {
        dp->th_opcode=htons((u_short)DATA);
        dp->th_block=htons((u_short)1);
        if ((*TFTPread)(dat,(long*)(&size),1,argu)!=0)
        {
            closesocket(dataSocket);
            free(buf);
            free(ackbuf);
            return 255;
        }
        size+=4;
        nextBlockNumber=1;
    }

    do
    {
      ntimeout=0;
      do
      {
         if (ntimeout==NumberTimeOut)
         {
             closesocket(dataSocket);
             free(buf);
             free(ackbuf);
             return 255;
         }

         if (sendto(dataSocket,(const char *)dp,size,0,(struct sockaddr *)&to,tolen)!=size)
         {
             closesocket(dataSocket);
             free(buf);
             free(ackbuf);
             return 255;
         }

         do
         {
             n=-1;
             FD_ZERO(&lecture);
             FD_SET(dataSocket,&lecture);

             tv.tv_sec=TimeOut; tv.tv_usec=0;
             if ((i=select(dataSocket+1, &lecture, NULL, NULL, &tv))==-1)
             {
                closesocket(dataSocket);
                free(buf);
                free(ackbuf);
                return 255;
             }

             if (i>0) // = time out not expired
                n=recvfrom(dataSocket, (char*)ap, vPKTSIZE, 0,(struct sockaddr *)&from, (int *)&fromlen);
         } while ((n<0)&&(i>0));

         if (i>0)
         {
            to.sin_port=from.sin_port;
            ap->th_opcode = ntohs((u_short)ap->th_opcode);
            ap->th_block = ntohs((u_short)ap->th_block);
            if (ap->th_opcode != ACK)
            {
                closesocket(dataSocket);
                free(buf);
                free(ackbuf);
                return 255;
            }

            if (ap->th_block != nextBlockNumber)
            {
               /* Re-synchronize with the other side */
               ioctlsocket(dataSocket, FIONREAD, (u_long *)&i); //i=number of byte in read-buffer
               while (i)
               {
                  recv(dataSocket, (char *)ap, vPKTSIZE, 0);
                  ioctlsocket(dataSocket, FIONREAD, (u_long *)&i);
               }
               ap->th_block=nextBlockNumber+1;
            }
         }
         ntimeout++;
      } while (ap->th_block!=nextBlockNumber);

      if ((size<vPKTSIZE)&&(nextBlockNumber!=0)) break;

      nextBlockNumber++;
      dp->th_block=htons(nextBlockNumber);
      if (nextBlockNumber==1)
      {
         dp->th_opcode=htons((u_short)DATA);
         i=(*TFTPread)(dat,(long*)(&size),1,argu);
      } else
      {
         Oldsize=size;
         if (Oldsize==vPKTSIZE)
             i=(*TFTPread)(dat,(long*)(&size),0,argu);
         else
             i=0;
      }
      if (i)
      {
         closesocket(dataSocket);
         free(buf);
         free(ackbuf);
         return i;
      }

      size+=4;
   } while (Oldsize==vPKTSIZE);
   closesocket(dataSocket);
   free(buf);
   free(ackbuf);
   return 0;
}

int tftp_send(struct sockaddr_in *to1,char *name,char *mode,int InClient,
              char (*TFTPread)(char *,long *,char,void *),
              void *argu)
{
    return tftp_send_ext(to1,name,mode,InClient,TFTPread,argu,PKTSIZE);
}

int tftp_send_buffer(struct sockaddr_in *to,char *name,char *mode,char *datas,DWORD l)
{
    TFTParg_buffer a;
    a.dat=datas;
    a.l=l;
    return tftp_send(to,name,mode,1,TFTPsSendBuffer,&a);
}

open_sok.cpp socket opener

#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>

#pragma   comment(lib,   "ws2_32.lib")


static struct sockaddr_in address;
int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address)
{
  SOCKET desc;                  
  unsigned int length=sizeof(struct sockaddr_in);

  if ((desc = socket(AF_INET, type, 0)) == INVALID_SOCKET)
  {
    printf(" Error Cannot Create Socket!\n ");
    return -1;
  }


  address.sin_family=AF_INET;
  address.sin_addr.s_addr=htonl(INADDR_ANY);
  address.sin_port=htons(*ptr_port); 

  if (bind(desc,(sockaddr *)&address,length) == SOCKET_ERROR)
  {

      printf("Socket attchment impossible. AND the error is %d\n", WSAGetLastError());
      closesocket(desc);
    return -1;
  }


  if (ptr_address!=NULL)
     getsockname(desc,(sockaddr *)ptr_address, (int *)&length);
  return desc;
}

Edited 10 Months Ago by Dani: Formatting fixed

Maybe try getaddrinfo(name, port, &amp;hints, &amp;result). There is an example at the bottom of the page.

pNodeName: A pointer to a NULL-terminated ANSI string that contains a host (node) name or a numeric host address string. For the Internet protocol, the numeric host address string is a dotted-decimal IPv4 address or an IPv6 hex address.

Looks like MS gethostbyname(name) doesn't take dot format and is deprecated.

name: A pointer to the null-terminated name of the host to resolve.

Note

The gethostbyname function has been deprecated by the introduction of the getaddrinfo function. Developers creating Windows Sockets 2 > applications are urged to use the getaddrinfo function instead of gethostbyname.

Edited 4 Years Ago by histrungalot: Adding

This article has been dead for over six months. Start a new discussion instead.