#include #include #include #include #include #include #include #include struct in_addr* name_to_IP_addr(char* hostname) { int error; struct addrinfo* addressInfo; /* Convert hostname into IP address */ error = getaddrinfo(hostname, NULL, NULL, &addressInfo); if(error) { return NULL; } /* Return first address in list */ return &(((struct sockaddr_in*)(addressInfo->ai_addr))->sin_addr); } int connect_to(struct in_addr* ipAddress, int port) { struct sockaddr_in socketAddr; int fd; /* Create socket, SOCK_STREAM means TCP */ fd = socket(AF_INET, SOCK_STREAM, 0); if(fd < 0) { perror("Error creating socket"); exit(1); } socketAddr.sin_family = AF_INET; /* Internet v4 family of protocols */ socketAddr.sin_port = htons(port); /* Port num - converted to network ** byte order */ socketAddr.sin_addr.s_addr = ipAddress->s_addr; /* IP address of server */ /* Connect socket to the given address */ if(connect(fd, (struct sockaddr*)&socketAddr, sizeof(socketAddr)) < 0) { perror("Error connecting"); exit(1); } /* Have connected file descriptor */ return fd; } void send_HTTP_request(int fd, char* file, char* host) { char* requestString; /* Wrong original code: requestString = (char*)malloc(strlen(file) + 20);*/ requestString = (char*)malloc(strlen(file) + strlen(host) + 26); /* Create request string to send: GET / HTTP/1.0 Host: hostname */ sprintf(requestString, "GET %s HTTP/1.0\r\nHost: %s\r\n\r\n", file, host); /* Send our request via fd (i.e. to server */ /* Could have used fdopen then fprintf */ /* Should really loop to ensure all bytes are sent - note that write() * returns number of bytes sent, or -1 on error */ if(write(fd, requestString, strlen(requestString)) < 1) { perror("Write error"); exit(1); } } void get_and_output_HTTP_response(int fd) { char buffer[1024]; int numBytesRead; int eof = 0; /* Repeatedly loop until data received */ while(!eof) { /* Read up to 1024 bytes */ numBytesRead = read(fd, buffer, 1024); if(numBytesRead < 0) { perror("Read error\n"); exit(1); } else if(numBytesRead == 0) { /* End of file - connection closed */ eof = 1; } else { /* Write out bytes to standard output */ /* Using fwrite allows for null characters in data */ fwrite(buffer, 1, numBytesRead, stdout); /* Original code incorrectly used STDOUT_FILENO as second arg */ } } } int main(int argc, char* argv[]) { int fd; struct in_addr* ipAddress; char* hostname; if(argc != 2) { fprintf(stderr, "Usage: %s hostname\n", argv[0]); exit(1); } hostname = argv[1]; /* Convert hostname to IP address */ ipAddress = name_to_IP_addr(hostname); if(!ipAddress) { fprintf(stderr, "%s is not a valid hostname\n", hostname); exit(1); } fd = connect_to(ipAddress, 80); send_HTTP_request(fd, "/", hostname); get_and_output_HTTP_response(fd); close(fd); return 0; }