// client.c -- open an internet socket and talk into it. /* Derived from isockt.c (C) 1991 Blair P. Houghton, All Rights Reserved, copying and distribution permitted with copyright intact. Modified in 1993 to remove pre-ANSI code by Michael J. Fischer Modified 2010 to improve style and clarity by Michael J. Fischer and Alice E. Fischer */ #include "tools.h" // Shorter names for system structures typedef struct sockaddr_in sockInfo; typedef struct sockaddr sockUnion; typedef struct hostent hostInfo; // ----------------------------------------------------------------------------- // Data to send to remote server const char* const line[] = { "Politeness, by Alan Alexander Milne\n", "When people ask me,", "I always tell them:", "\"Quite well, thank you, I'm very glad to say.\"", "If people ask me,", "I always answer,", "\"Quite well, thank you, how are you to-day?\"", "I always answer,", "I always tell them,", "If they ask me", "Politely.....", "BUT SOMETIMES\n", "I wish\n", "That they wouldn't.\n" }; const int nLines = sizeof line / sizeof line[0]; // ----------------------------------------------------------------------------- // Prototypes void openConnection(const char* host, int port, FILE** remoteInP, FILE** remoteOutP); // ----------------------------------------------------------------------------- // arg 1 is remote host; arg 2 is port number of listener on remote host int main(int argc, char *argv[]) { char buf[BUFSIZ + 1]; int k, nBytes, status; char* ret; FILE* remoteIn; FILE* remoteOut; // collect command line arguments const char* prog = argv[0]; if (argc != 3) fatal("usage: %s hostname portno\n", prog); const char* hostName = argv[1]; int port = atoi(argv[2]); // open socket connection openConnection(hostName, port, &remoteIn, &remoteOut); // wait for server to acknowledge the connection. ret = fgets(buf, BUFSIZ, remoteIn); if (!ret) fatalp("%s: Error while reading from socket.", prog); printf("%s", buf); // write lines of text, one per second, until message is complete. for (k = 0; k < nLines; k++) { sleep(1); printf("Writing to socket: %s\n", line[k]); nBytes = fprintf(remoteOut, "%s\n", line[k]); if (nBytes <= 0) fatalp("%s: Error while writing to socket.", prog); fflush(remoteOut); // force line to go out } // Close socket streams status = fclose(remoteIn); if (status) fatalp("Error closing input stream on socket"); status = fclose(remoteOut); if (status) fatalp("Error closing output stream on socket"); exit(0); } // ----------------------------------------------------------------------------- // Opens a connection to given host and port. // Returns open streams for reading and writing to the connection. // Both streams should be closed when done with the connection. // All errors result in an error message followed by termination. void openConnection(const char* hostName, int port, FILE** remoteInP, FILE** remoteOutP) { int status; // Make a net socket, using stream mode, with protocol irrelevant ( == 0 ) int sockFd = socket(AF_INET, SOCK_STREAM, 0); if (sockFd < 0) fatalp("Can't to create socket"); // get host IP address hostInfo* remoteHost = gethostbyname(hostName); if (remoteHost == NULL) fatalp("unknown host: %s\n", hostName); // create an address structure for the peer socket sockInfo peer; peer.sin_family = AF_INET; memmove(&peer.sin_addr, remoteHost->h_addr_list[0], remoteHost->h_length); peer.sin_port = htons(port); // connect local socket to its peer status = connect(sockFd, (sockUnion*) &peer, sizeof peer); if (status < 0) fatalp("connection to %s refused.", hostName); // create buffered input and output streams on the new socket // we use dup() so that each stream has its own file descriptor *remoteOutP = fdopen(sockFd, "w"); if (!*remoteOutP) fatalp("Can't create output stream"); int sockFd2 = dup(sockFd); if (sockFd2 < 0) fatalp("Can't duplicate socket file descriptor"); *remoteInP = fdopen(dup(sockFd), "r"); if (!*remoteOutP) fatalp("Can't create input stream"); }