So, as always, I'll preface this email by saying this is for a class assignment. I'm looking for debugging assistance.
I have two files running on two machines. The sending program is taking 100 byte chunks of a file, adding a header file, adding a crc-16 tail and sending the message to the remote server. The remote server is validating the code, ensuring it's not duplicated and sending an ack back to the local machine.
My problem is this...I'm not seeing the output I'd expect when the file is longer than 1 frame. (>100 bytes). The program works perfectly when the file is only 1 frame long.
File: send.c
Code:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFMAX 128
//Command Arguments:
// [0] - sendf
// [1] - destination machine
// [2] - destination port number
// [3] - file to be sent
int main(int argc, char* argv[]){
int sk; // Socket
int n; // # of char read to buffer
int i; // Looping Index
int fin; // Final Frame 1=true 0=false
int seq; // Frame Seq No
int ack; // Frame Ack
unsigned char buf[BUFMAX]; // Send Buffer
unsigned char res[BUFMAX]; // Response Buffer
unsigned short reply; // CRC Reply
struct sockaddr_in remote;
struct hostent *hp;
// Define and open the input file for transfer
FILE *fp;
fp = fopen(argv[3],"r");
// Create the socket
sk = socket(AF_INET, SOCK_DGRAM, 0);
remote.sin_family = AF_INET;
hp = gethostbyname(argv[1]);
// If the host cannot be found terminate program
if(hp==NULL){
printf("Can't find hostname. %s\n", argv[1]);
exit(1);
}
bcopy(hp->h_addr, &remote.sin_addr.s_addr, hp->h_length);
remote.sin_port = ntohs(atoi(argv[2]));
seq = 1; // set the initial seq
fd_set rfds;
struct timeval tv;
int retval;
FD_ZERO(&rfds);
FD_SET(sk, &rfds);
// Read 100 bytes at a time from the file to the buffer
while((n=fread(&buf[1], 1, 100, fp)>0)){
printf("Preparing to send a new frame!\n");
printf("%d bytes read to buffer.\n", strlen(buf));
for(i=1; i<strlen(buf); i++){ printf("%c", buf[i]); }
printf("\n");
// Prepare header byte
// fin = 1 << 5;
// seq = 1 << 2;
// ack = 1;
if(strlen(buf)<100){ // Is this the final frame?
printf("Found the final frame! %d\n", strlen(buf));
fin = 1 << 5; // Set the 6th bit to 1
} else {
fin = 0;
}
seq = (seq == 0) ? 1 : 0; // Need to alternate seq no
seq = seq << 2;
ack = 0; // Not needed for the sendf function
buf[0] = fin | seq | ack; // Bitwise or to set the header
printf("Preparing Header: %x\n", buf[0]);
// Generate CRC Code //
reply = crc(&buf, strlen(buf));
buf[strlen(buf)] = reply >> 8 & 0xff;
buf[strlen(buf)] = reply & 0xff;
printf("Did I get here?\n");
for(i=0; i<strlen(buf); i++){ printf("buf[%i] = %02x\n", i, buf[i]); }
// Send to the remote machine //
while(1){
dlsendto(sk, buf, strlen(buf)+1, 0, &remote,sizeof(remote),0);
// Stop and Wait for a response from the remote machine //
tv.tv_sec = 10;
tv.tv_usec = 0;
if(select(32, &rfds, NULL, NULL, &tv)==0){
printf("Timeout - resending the frame!!\n");
}
else {
read(sk,res,BUFMAX);
reply = crc(res, strlen(res));
if(crc(res, strlen(res))==0){ // Is CRC Correct?
if(((res[0] << 5) & 0x80) == seq){ // Is Seq Correct?
if(((res[0] << 7) & 0x80)){ // Is Ack?
printf("Ack Received\n");
//buf[1] = '\0';
break;
}
else{
printf("Not an Ack! Resend Frame!\n");
}
}
else {
printf("Duplicate Ack Received! Resend Frame!\n");
}
}
else {
printf("Ack Frame Damaged! Resend Frame!\n");
}
}
} //printf("Exited to here\n");
}
close(sk);
}
The output I'm getting looks like this....
Code:
Preparing to send a new frame!
101 bytes read to buffer.
total 4945
-rwxr-xr-x 1 root root 57548 2005-01-29 12:20 afio
-rwxr-xr-x 1 root root 3200 2006-05Preparing Header: 0
Did I get here?
Ack Received
Preparing to send a new frame!
0 bytes read to buffer.
Found the final frame! 0
Preparing Header: 24
Did I get here?
buf[0] = 24
... <intentionally removed for space>
buf[102] = c1
Duplicate Ack Received! Resend Frame!
Timeout - resending the frame!!
Timeout - resending the frame!!
Notice that the first read appears to work fine. One the second read, it thinks I'm not reading anything into the buffer so it turns the final frame bit on.
For reference, my header should be:
8 - 0
7 - 0
6 - final frame? 1 = yes; 0 = no;
5 - 0
4 - 0
3 - sequence - alternates between 1 and 0
2 - 0
1 - ack? 1 = yes; 0 = no;
Hoping some fresh eyes might see what I'm doing wrong. If you need it, I can also post the receive program.