/* checks to make sure the server can work when a client leaves it hanging... */ #include /* standard C i/o facilities */ #include /* needed for atoi() */ #include /* defines STDIN_FILENO, system calls,etc */ #include /* system data type definitions */ #include /* socket specific definitions */ #include /* INET constants and stuff */ #include /* IP address conversion stuff */ #include /* gethostbyname */ #include #include "support.h" int waitandack(int sk, struct sockaddr_in *s,int bnum) { char buff[1000]; int len; int opcode,block; if ((len=wait_for_response(sk,s,buff,1000))==0) { printf("No Response from server\n"); return(0); } opcode = get_opcode(buff); block = get_blocknum(buff); if ((opcode != DATA) || (block != bnum)) { printf("Invalid (not what I expected!)\n"); print_msg(buff,len); return(-1); } printf("Got block %d (%d)\n",block,len); build_ack(buff,block); if (sendto(sk,buff,4,NULL,(struct sockaddr*)s,sizeof(*s))<0) { perror("Error sending"); return(0); } printf("Sending ACK for block %d: ",block); print_msg(buff,4); return(len); } int waitforresend(int sk, struct sockaddr_in *s,int bnum) { char buff[1000]; int len; int opcode,block; int waits=0; while (waits<4) { if ((len=wait_for_response(sk,s,buff,1000))==0) { if (waits<4) { waits++; continue; } else { printf("No resend of block received %d\n",bnum); return(0); } } opcode = get_opcode(buff); block = get_blocknum(buff); if ((opcode != DATA) || (block != bnum)) { printf("Invalid (not what I expected!) waiting for resend \n"); return(0); } break; } printf("Get a restransmission from server: block %d\n",bnum); return(1); } int partialfiletransfer(int sk, struct sockaddr_in *sorig, char *filename) { int sent; char buff[1000]; int len; int bnum=1; struct sockaddr_in s; memcpy(&s,sorig,sizeof(s)); len = build_request(buff,RRQ,filename,"octet"); printf("Sending RRQ: "); print_msg(buff,len); sent = sendto(sk,buff,len,NULL,(struct sockaddr*)&s,sizeof(s)); while (bnum<4) { if ( (len=waitandack(sk,&s,bnum))==0) { printf("Error with client\n"); return(0); } if (len!=516) { printf("Premature completion!\n"); break; } bnum++; } printf("Leaving server hanging after block %d\n",bnum); if (! waitforresend(sk,&s,bnum)) { printf("ERROR: NO RETRANSMISSION\n"); return(0); } if (! waitforresend(sk,&s,bnum)) { printf("ERROR: NO RETRANSMISSION\n"); return(0); } return(1); } int filetransfer(int sk, struct sockaddr_in *sorig, char *filename) { int sent; char buff[1000]; int len; int bnum=1; struct sockaddr_in s; memcpy(&s,sorig,sizeof(s)); len = build_request(buff,RRQ,filename,"octet"); printf("Sending RRQ: "); print_msg(buff,len); sent = sendto(sk,buff,len,NULL,(struct sockaddr*)&s,sizeof(s)); while (1) { if ( (len=waitandack(sk,&s,bnum))==0) { printf("Error with client\n"); return(0); } if (len!=516) { return(1); } bnum++; } return(0); } /* client program: The following must passed in on the command line: hostname of the server (argv[1]) port number of the server (argv[2]) file name (argv[3]) */ int main( int argc, char **argv ) { int sk,sk2; struct sockaddr_in server; struct hostent *hp; /* Make sure we have the right number of command line args */ if (argc!=4) { printf("Usage: %s \n",argv[0]); exit(0); } /* create a socket IP protocol family (PF_INET) UDP (SOCK_DGRAM) */ if ((sk = socket( PF_INET, SOCK_DGRAM, 0 )) < 0) { printf("Problem creating socket\n"); exit(1); } if ((sk2 = socket( PF_INET, SOCK_DGRAM, 0 )) < 0) { printf("Problem creating socket\n"); exit(1); } server.sin_family = AF_INET; if ((hp = gethostbyname(argv[1]))==0) { printf("Invalid or unknown host\n"); exit(1); } /* copy the IP address into the sockaddr It is already in network byte order */ memcpy( &server.sin_addr.s_addr, hp->h_addr, hp->h_length); /* establish the server port number - we must use network byte order! */ server.sin_port = htons(atoi(argv[2])); partialfiletransfer(sk,&server,argv[3]); if (!filetransfer(sk2,&server,argv[3])) { printf("TIMEOUT: ERROR Server not responding\n"); } else { printf("TIMEOUT: OK\n"); } return(0); }