#include #include #include #include #include #include #include #include #include #include #include using namespace std; /* Google AI wrote this */ long getFileSize(const char *filename) { struct stat st; if (stat(filename, &st) == 0) { return st.st_size; // Returns the file size in bytes } else { perror("Error getting file size"); // Prints error if stat fails return -1; // Indicates an error } } /* Client should send a length of filename, then filename */ void handle_client(int client_fd, struct sockaddr_in client_address){ int64_t file_size; int file_fd; char *file_space, *filename; printf("Connection made from address %s\n", inet_ntoa(client_address.sin_addr)); uint16_t filename_length; if(2 != recv(client_fd, &filename_length, 2, MSG_WAITALL)) goto exit; filename = (char*)malloc(filename_length + 1); filename[filename_length] = 0; if(filename_length != recv(client_fd, filename, filename_length, MSG_WAITALL)) goto exit; printf("Opening file \"%s\" for client on fd %d\n", filename, client_fd); file_fd = open(filename, O_RDONLY); if(file_fd < 0){ perror("open"); file_size = -1; write(client_fd, &file_size, 8); goto exit; } file_size = getFileSize(filename); file_space = (char*)malloc(file_size); // 10 megs if(file_size != read(file_fd, file_space, file_size)){ printf("Error reading file %s\n", filename); goto exit; } free(file_space); free(filename); close(file_fd); // Send file size first write(client_fd, &file_size, 8); // Then send actual file write(client_fd, file_space, file_size); exit: close(client_fd); } int main(int argc, char ** argv){ struct sockaddr_in sad; sad.sin_port = htons(5143); sad.sin_addr.s_addr = INADDR_ANY; sad.sin_family = AF_INET; int skt = socket(AF_INET, SOCK_STREAM, 0); // Step 1 if(skt == -1){ perror("socket"); return 1; } if( bind(skt, (struct sockaddr*)(&sad), sizeof(struct sockaddr_in)) ){ // step 2 perror("bind"); return 1; } if( listen(skt, 5) ){ // step 3 perror("listen"); return 1; } while(1){ int client_fd; struct sockaddr_in client_address; socklen_t address_size = sizeof(struct sockaddr_in); client_fd = accept(skt, (struct sockaddr *)(&client_address), &address_size); // step 4 thread client_thread(handle_client, client_fd, client_address); client_thread.detach(); } return 0; }