#include #include #include #include #include #include #include #include #include #include #define PACKET_SIZE 64 #define PACKET_DATA (PACKET_SIZE - 4) #define HEADER_SIZE 4 #define BUFFER_SIZE ((0x100000 / PACKET_DATA) * PACKET_DATA) // Delay between packets in useconds for asynchronous mode. #define ASYNCHRONOUS_DELAY 1000000 // Send packets as fast as possible, using a timer #define ASYNCHRONOUS // Commands sent by receiver #define RESEND 0x1 #define START 0x2 #define FILENAME 0x3 char HOSTNAME[1024]; char INFILE[1024]; int PORT; FILE *in; char data[PACKET_SIZE]; int write_socket; typedef struct { struct timeval start_time; struct timeval last_time; int64_t bytes_transferred; int64_t total_bytes; } status_t; status_t status; void init_status(status_t *status) { gettimeofday(&status->start_time, 0); gettimeofday(&status->last_time, 0); status->bytes_transferred = 0; status->total_bytes = 0; } void update_status(status_t *status, int bytes) { struct timeval new_time; status->bytes_transferred += bytes; status->total_bytes += bytes; gettimeofday(&new_time, 0); if(new_time.tv_sec - status->last_time.tv_sec > 2) { fprintf(stderr, "%ld bytes sent. %ld bytes/sec \n", status->total_bytes, (int64_t)status->bytes_transferred / (int64_t)(new_time.tv_sec - status->start_time.tv_sec)); fflush(stdout); gettimeofday(&status->start_time, 0); gettimeofday(&status->last_time, 0); status->bytes_transferred = 0; // status->last_time = new_time; }; } void stop_status() { fprintf(stderr, "\nDone.\n"); } int read_int32(char *data) { unsigned int a, b, c, d; a = (unsigned char)data[0]; b = (unsigned char)data[1]; c = (unsigned char)data[2]; d = (unsigned char)data[3]; return (a << 24) | (b << 16) | (c << 8) | (d); } int send_packet(int packet_number) { fseek(in, packet_number * PACKET_DATA, SEEK_SET); int bytes_read = fread(data + 4, 1, PACKET_DATA, in); data[0] = (packet_number >> 24) & 0xff; data[1] = (packet_number >> 16) & 0xff; data[2] = (packet_number >> 8) & 0xff; data[3] = packet_number & 0xff; int size = bytes_read + 4; int i; printf("send_packet %d size=%d\n", __LINE__, size); for(i = 0; i < size; i++) printf("%02x ", data[i]); printf("\n"); int bytes_written = write(write_socket, data, size); /* * printf("bytes_written=%d packet_number=%lld\n", * bytes_written, * packet_number); */ packet_number++; return packet_number; } int main(int argc, char *argv[]) { if(argc < 4) { printf("Usage: udpsend \n"); exit(1); } strcpy(HOSTNAME, argv[1]); PORT = atoi(argv[2]); strcpy(INFILE, argv[3]); int64_t total_bytes = 0; int i; printf("HOSTNAME=%s\n" "PORT=%d\n" "INFILE=%s\n" "ASYNCHRONOUS=%s\n", HOSTNAME, PORT, INFILE, #ifdef ASYNCHRONOUS "yes" #else "no" #endif ); write_socket = socket(PF_INET, SOCK_DGRAM, 0); struct sockaddr_in write_addr; struct hostent *hostinfo; write_addr.sin_family = AF_INET; write_addr.sin_port = htons((unsigned short)PORT); hostinfo = gethostbyname(HOSTNAME); if(hostinfo == NULL) { fprintf (stderr, "main: unknown host %s.\n", HOSTNAME); exit(1); } write_addr.sin_addr = *(struct in_addr *)hostinfo->h_addr; if(connect(write_socket, (struct sockaddr*)&write_addr, sizeof(write_addr)) < 0) { perror("main: connect"); } int read_socket = socket(PF_INET, SOCK_DGRAM, 0); struct sockaddr_in read_addr; read_addr.sin_family = AF_INET; read_addr.sin_port = htons((unsigned short)PORT); read_addr.sin_addr.s_addr = htonl(INADDR_ANY); if(bind(read_socket, (struct sockaddr*)&read_addr, sizeof(read_addr)) < 0) { perror("main: bind"); } int is_stopped = 0; #ifndef ASYNCHRONOUS is_stopped = 1; #endif init_status(&status); int packet_number = 0; // Send filename and size struct stat file_status; bzero(&file_status, sizeof(struct stat)); stat(INFILE, &file_status); uint64_t file_size = file_status.st_size; char *ptr = data; *ptr++ = FILENAME; strcpy(ptr, INFILE); ptr += strlen(INFILE); *ptr++ = 0; *ptr++ = (file_size >> 56) & 0xff; *ptr++ = (file_size >> 48) & 0xff; *ptr++ = (file_size >> 40) & 0xff; *ptr++ = (file_size >> 32) & 0xff; *ptr++ = (file_size >> 24) & 0xff; *ptr++ = (file_size >> 16) & 0xff; *ptr++ = (file_size >> 8) & 0xff; *ptr++ = file_size & 0xff; int size = ptr - data; printf("main %d size=%d\n", __LINE__, size); for(i = 0; i < size; i++) printf("%02x ", data[i]); printf("\n"); write(write_socket, data, size); usleep(ASYNCHRONOUS_DELAY); in = fopen(INFILE, "r"); while(1) { // Get receiver request fd_set read_set; struct timeval tv; FD_ZERO(&read_set); FD_SET(read_socket, &read_set); tv.tv_sec = 0; tv.tv_usec = 0; int read_status = 0; if(is_stopped) read_status = select(read_socket + 1, &read_set, 0, 0, 0); else read_status = select(read_socket + 1, &read_set, 0, 0, &tv); if(read_status > 0) { int bytes_read = read(read_socket, data, PACKET_SIZE); if(bytes_read) { switch(data[0]) { case RESEND: { is_stopped = 1; if(bytes_read > 4) { int packet_number = read_int32(data + 1); //printf("resending packet %d\n", packet_number); send_packet(packet_number); update_status(&status, PACKET_DATA); } break; } case START: if(bytes_read > 4) { packet_number = read_int32(data + 1); is_stopped = 0; } break; } } } if(!is_stopped) { //printf("sent packet %d\n", packet_number); #ifdef ASYNCHRONOUS usleep(ASYNCHRONOUS_DELAY); #endif packet_number = send_packet(packet_number); total_bytes += PACKET_DATA; update_status(&status, PACKET_DATA); // Wait for confirmation every buffer size if(!(status.total_bytes % BUFFER_SIZE) || total_bytes >= file_size) is_stopped = 1; } } }