/* This program causes tiny.c to crash because this program closes the socket immediately after making requests from tiny. This causes tiny to write to a closed socket. This example is built from the client-template.c program. */ #include // for fprintf() #include // for atoi() and exit() #include // for memset(), bzero(), bcopy(), and strerror() #include // for errno #include // for close(), write() #include // for socket(), connect(), AF_INET, SOCK_STREAM #include // for sockaddr_in, htons() #include // for gethostbyname(), hostent, hstrerror(), and h_errno // prototypes for two error handling functions (defined below) void unix_error(char *msg); void dns_error(char *msg); int main(int argc, char **argv) { int socket_fd; // socket descriptor struct hostent *hp; // used to get server IP address struct sockaddr_in serveraddr; // server address structure if (argc != 3) { fprintf(stderr, "usage: %s \n", argv[0]); exit(0); } // Create a reliable, stream socket using TCP. if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) unix_error("socket error"); // Construct the server address structure. bzero(&serveraddr, sizeof(serveraddr)); // zero out the address structure memset(&serveraddr, 0, sizeof(serveraddr)); // zero out the address structure serveraddr.sin_family = AF_INET; // Internet address family if ( (hp = gethostbyname( argv[1] )) == NULL ) // fill in server's IP address dns_error("gethostbyname error"); bcopy(hp->h_addr, (struct sockaddr *)&serveraddr.sin_addr, hp->h_length); serveraddr.sin_port = htons( atoi(argv[2]) ); // fill in the port number // Establish a connection with the server. if (connect(socket_fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) unix_error("connect error"); // We need to make two requests to tiny so that it writes two times // to the closed socket (tiny crashes on the second write to the // closed socket). See CS-APP, page 841, the "Aside". //(Can you replace the two (short) requests with one large request?) write(socket_fd, "GET / HTTP/1.0\r\n\r\n", 18); write(socket_fd, "GET /godzilla.gif HTTP/1.0\r\n\r\n", 30); //write(socket_fd, "GET /cgi-bin/adder?2&3 HTTP/1.0\r\n\r\n", 35); // don't send the blank line after the request command. //write(socket_fd, "GET /godzilla.gif HTTP/1.0\r\n", 30); if (close(socket_fd) < 0) unix_error("close error"); exit(0); }//main /* Below are two error handling functions. They provide reasonably meaningful error messages. */ void unix_error(char *msg) { fprintf(stderr, "%s: %s\n", msg, strerror(errno)); exit(1); } void dns_error(char *msg) { fprintf(stderr, "%s: %s\n", msg, hstrerror(h_errno)); exit(1); }