Appendix F

Appendix F contains the code listing for the UDP-based file transmission programs mentioned in Chapter 2.

// *********************************

// * UDP-based File Transfer Server

// * Filename: UDPserver.c

// *********************************

#include <stdio.h>

#include <windows.h>

#include <io.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <errno.h>

#include <time.h>

#define MYPORT 8080

#define MPEG_FILE "test.mpg"

#define BLOCK 1024

int net_init();

void render_MPEG(SOCKET sd);

int open_MPEG(int* fdptr);

void sleep(clock_t wait);

struct UDP_packet { // defining my own packet

int seqnum;

char payload[BLOCK];

};

void main(void) {

int sd;

if ( (sd = net_init()) < 0 )

exit(0);

render_MPEG(sd);

closesocket(sd);

WSACleanup();

}

// FUNCTION net_init initializes connectionless oriented sockets -- UDP!

int net_init() {

int sd;

struct sockaddr_in myaddr;

WSADATA WsaData;

WORD wVersionRequested;

int err;

wVersionRequested = MAKEWORD(1, 1);

if ( (err = WSAStartup(wVersionRequested, &WsaData)) != 0 ) {

printf("Could not find WinSock 1.1 DLL\n");

return -1;

}

if ( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))

== INVALID_SOCKET) {

printf("socket error %d\n", WSAGetLastError());

return -1;

}

// bind it!!

memset( (char *)&myaddr, 0x00, sizeof(myaddr) );

myaddr.sin_family = AF_INET;

myaddr.sin_port = htons(MYPORT);

myaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(sd, (struct sockaddr *)&myaddr, sizeof(myaddr))

== SOCKET_ERROR) {

printf("Bind error %d\n", WSAGetLastError());

return -1;

}

return sd;

}

//FUNCTION render_MPEG transmits MPEG data to client

void render_MPEG(SOCKET sd) {

int recvN, sendN, addrlen;

int fd, filesize, nread;

struct sockaddr_in clientaddr;

char *r_buffer, *s_buffer;

BYTE terminator;

int c=0, i=0, datasize=0, x;

struct UDP_packet my_packet;

clock_t start_t, stop_t; // for timing the transmission

double duration;

addrlen = sizeof(clientaddr);

my_packet.seqnum = 0; // initially

// each time server recvs, it's a request!

printf("Waiting to recv from client...\n");

r_buffer = (char *)malloc(BLOCK);

addrlen = sizeof(clientaddr);

recvN = recvfrom(sd, r_buffer, BLOCK, 0,

(struct sockaddr *)&clientaddr, &addrlen);

if (recvN == SOCKET_ERROR) {

printf("recvfrom error %d\n", WSAGetLastError());

return;

}

// open the file

if ( (filesize = open_MPEG(&fd)) < 0)

return;

s_buffer = (char *)malloc(BLOCK);

start_t = clock();

// send out MPEG data

while (filesize-c != 0) {

if ( (nread = _read(fd, my_packet.payload, BLOCK)) < 0 ) {

printf("_read error %d\n", errno);

return;

}

c += nread; // keep track of how many bytes read fr file

x = sizeof(my_packet.seqnum);

sendN = sendto(sd, (char *)&my_packet, nread+x, 0,

(struct sockaddr *)&clientaddr, addrlen);

if (sendN == SOCKET_ERROR) {

printf("sendto error %d\n", WSAGetLastError());

return;

}

i = nread+x; // total supposed to have been sent out, vs sendN

datasize += sendN-x; //bytes of MPEG file already sent out

if ( sendN != i) {

printf("Eeek!! bytes actually sent diff %d vs %d\n", i, sendN);

break;

}

my_packet.seqnum++; // next pkt's seqnum

}//end while

_close(fd);

stop_t = clock();

duration = (double)(stop_t-start_t)/CLOCKS_PER_SEC;

printf("Total packets sent: %d\n", my_packet.seqnum);

printf("Total %d bytes of MPEG data sent\n", datasize);

printf("Time taken %2.2f\n", duration);

printf("Now sending a terminator\n");

// send a byte of value 0x0000 to indicate termination

terminator = 0xff;

my_packet.payload[0] = terminator;

sendN = sendto(sd, (char *)&my_packet,

sizeof(BYTE)+sizeof(my_packet.seqnum), 0,

(struct sockaddr *)&clientaddr, addrlen);

if (sendN == SOCKET_ERROR)

printf("sendto error %d\n", WSAGetLastError());

}

// FUNCTION open_MPEG opens file, assigns a descriptor

// and returns filesize

int open_MPEG(int* fdptr) {

struct _stat file_stat;

if (_stat(MPEG_FILE, &file_stat) < 0) {

if (errno == ENOENT)

printf("File %s not found\n");

else

printf("_stat error unknown %d\n", errno);

return -1;

}

if ( (*fdptr = _open(MPEG_FILE, _O_RDONLY|_O_BINARY)) == -1 ) {

printf("_open error %d on file %s\n", errno, MPEG_FILE);

return -1;

}

return file_stat.st_size;

}

// FUNCTION sleep pauses for a specified number of seconds

void sleep(clock_t wait) {

clock_t goal;

goal = wait + clock();

while (goal > clock())

;

}

// *********************************

// * UDP-based File Transfer Client

// * Filename: UDPclient.c

// *********************************

#include <stdio.h>

#include <windows.h>

#include <io.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <time.h>

#define SERVER_PORT 8080

#define MY_PORT 6969

#define BLOCK 1024

#define MPEG_REQUEST "REQUEST"

#define MPEG_REQUEST_COMPLETE 0xff

#define RECORD "events.txt"

int net_init();

void get_MPEG(SOCKET sd, char *filename);

int open_MPEGfile(char *filename);

// define my own packet -- use it to recv incoming UDP packets

struct UDP_packet {

int seqnum;

char payload[BLOCK];

};

char SERVER_HOST[20];

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

int sd;

char filename[20];

if(argc < 2) {

printf("Usage: UDPtestClient [IPaddress]\n");

exit(0);

}

strcpy(SERVER_HOST, argv[1]);

printf("Enter a filename not more than 20 characters.\nIt must end with .mpg: ");

scanf("%s", filename);

if ( (sd = net_init()) < 0 ) {

closesocket(sd);

exit(0);

}

get_MPEG(sd, filename);

closesocket(sd);

WSACleanup();

}

int net_init() {

int sd;

struct sockaddr_in myaddr;

WSADATA WsaData;

WORD wVersionRequested;

int err;

wVersionRequested = MAKEWORD(1, 1);

err = WSAStartup(wVersionRequested, &WsaData);

if (err != 0) {

printf("Could not find WinSock 1.1 DLL\n");

return -1;

}

if ( (sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))

== INVALID_SOCKET ) {

printf("socket error %d\n", WSAGetLastError());

return -1;

}

// client must bind itself!!

ZeroMemory((char *)&myaddr, sizeof(myaddr));

myaddr.sin_family = AF_INET;

myaddr.sin_addr.s_addr = htonl(INADDR_ANY);

myaddr.sin_port = htons(MY_PORT);

if (bind(sd, (struct sockaddr *)&myaddr, sizeof(myaddr)) == SOCKET_ERROR) {

printf("client bind error %d\n", WSAGetLastError());

return -1;

}

return sd;

}


void get_MPEG(SOCKET sd, char *filename) {

int sendN, recvN, slen;

int fd, nwrite;

struct sockaddr_in servaddr;

char *s_buffer, *r_buffer;

int bytecount=0, c=0, x, prev_seqnum=-1, pktcount=0, lostpkt=0;

FILE *fp;

clock_t start_t, stop_t; // use for timing

double duration;

struct UDP_packet my_packet;

my_packet.seqnum = 0; // initially

// server's addr, etc !!

ZeroMemory((char *)&servaddr, sizeof(servaddr));

servaddr.sin_family = AF_INET;

servaddr.sin_addr.s_addr = inet_addr(SERVER_HOST);

servaddr.sin_port = htons(SERVER_PORT);

slen = sizeof(servaddr);

s_buffer = (char *)malloc(BLOCK);

sprintf(s_buffer, MPEG_REQUEST);

sendN = sendto(sd, s_buffer, strlen(s_buffer), 0,

(struct sockaddr *)&servaddr, sizeof(servaddr));

if (sendN == SOCKET_ERROR) {

printf("sendto error %d\n", WSAGetLastError());

return;

}

// open MPEG file

if ( (fd = open_MPEGfile(filename)) < 0)

return;

// also open a file to record events

if ( (fp = fopen(RECORD, "a+")) == NULL ) {

printf("Can't open file %s\n", RECORD);

return;

}

else

fprintf(fp, "MPEG file: %s\n", filename);

r_buffer = (char *)malloc(BLOCK);

start_t = clock();

// start recving data

while (1) {

if ( (recvN = recvfrom(sd, (char*)&my_packet,

BLOCK+sizeof(my_packet.seqnum), 0,

(struct sockaddr *)&servaddr, &slen)) == SOCKET_ERROR ) {

printf("recvfrom error %d\n", WSAGetLastError());

_close(fd);

return;

}

// packet loss encountered! Keep track of it

if (my_packet.seqnum != prev_seqnum+1) {

fprintf(fp, "Current pkt #%d not in sequence with prev pkt #%d\n",

my_packet.seqnum, prev_seqnum); // write to events file

// keeps track of lost pkts

lostpkt += my_packet.seqnum-(prev_seqnum+1);

}

pktcount++; // keeps track of total pkt recvd

if (recvN == sizeof(BYTE)+sizeof(my_packet.seqnum)) {

if (my_packet.payload[0] == 0xff) {

printf("Done!\n"); // recvd a terminator

break;

}

else {

printf("Hmmm ... seqnum%d\n", my_packet.seqnum);

break;

}

}

x = sizeof(my_packet.seqnum);

c += recvN - x;

if ( (nwrite = _write(fd, my_packet.payload, recvN-x)) < 0) {

printf("_write error %d\n", errno);

_close(fd);

return;

}

bytecount += nwrite;

if (c != bytecount) {

printf("total bytes recvd (%d) and written (%d) different\n", c,

bytecount);

break;

}

prev_seqnum = my_packet.seqnum;

} // end while

_close(fd);

stop_t = clock();

duration = (double)(stop_t-start_t)/CLOCKS_PER_SEC;

printf("Total pkts accounted for: %d\n", pktcount);

printf("Packets lost: %d\n", lostpkt);

printf("Total of %d bytes written to file\n", bytecount);

printf("Time taken %2.2f\n", duration);

// writing more statistical info to events file

fprintf(fp, "Total pkts received: %d\n", pktcount);

fprintf(fp, "Number of packets lost: %d\n", lostpkt);

fprintf(fp, "Total of %d bytes received\n", bytecount);

fprintf(fp, "Time taken: %2.2f seconds\n", duration);

fprintf(fp, "=======================================\n");

fclose(fp);

}

// FUNCTION open_MPEGfile opens the file & returns its descriptor

// returns -1 if failed

int open_MPEGfile(char *filename) {

int fd;

fd = _open(filename, _O_CREAT|_O_TRUNC|_O_RDWR|_O_BINARY,

_S_IREAD|_S_IWRITE);

if (fd < 0) {

printf("_open error %d on file %s\n", errno, filename);

return -1;

}

return fd;

}