In this section, we'll first write a threaded telnet client. This is a client that will request a connection to a socket, and then do what we specify above -- anything typed into standard input will go to the socket, and anything that comes from the socket will go to standard output.
The program is in src/th_telnet.c, and you should study it. The comments specify exactly what it is doing:
#include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "sockettome.h" /* As input, this procedure takes an array of two FILE *'s, typecast to a void *. Let's call this array "connection." This procedure will read lines of text from from connection[0] and write them to connection[1]. This is convenient, because it works regardless of whether the FILE *'s are socket connections or stdin/stdout. */ void *process_connection(void *c) { FILE **connection; char buf[1000]; connection = (FILE **) c; while (fgets(buf, 1000, connection[0]) != NULL) { printf("Read: %s", buf); fflush(stdout); fputs(buf, connection[1]); fflush(connection[1]); } exit(0); } int main(int argc, char **argv) { int fd; FILE *fin, *fout; FILE *stdin_to_socket[2]; FILE *socket_to_stdout[2]; pthread_t tid; if (argc != 3 || atoi(argv[2]) <= 0) { fprintf(stderr, "usage: th_telnet host port\n"); exit(1); } /* Open a socket connection to a server, and convert the file descriptor to two FILE *'s, one for reading and one for writing. */ fd = request_connection(argv[1], atoi(argv[2])); fin = fdopen(fd, "r"); fout = fdopen(fd, "w"); /* Create arrays of FILE *'s for process_connection. */ stdin_to_socket[0] = stdin; stdin_to_socket[1] = fout; socket_to_stdout[0] = fin; socket_to_stdout[1] = stdout; /* Fork off a thread to read from the socket and print to standard output. The main thread will read from standard input and print to the socket. */ if (pthread_create(&tid, NULL, process_connection, socket_to_stdout) != 0) { perror("pthread_create"); exit(1); } (void) process_connection(stdin_to_socket); return 0; } |
Let's try it, using alternate from the Socket lecture notes as the server:
UNIX> bin/th_telnet localhost 5555 Hey Read: Hey Read: Hey is for horses. Hey is for horses. I hate it when people say that. Read: I hate it when people say that. So stop saying that. Read: So stop saying that. Read: It is only proper. It is only proper. < CNTL-D > UNIX> |
UNIX> ../Sockets/bin/alternate localhost 5555 s Connection established. Client should start talking Hey Hey is for horses. I hate it when people say that. It is only proper. So stop saying that. UNIX> |
You'll note, when the left person wrote "So stop saying that," it was read and sent along the socket instantly. However, because alternate alternates strictly, it was not read from the socket until after the second person wrote "It is only proper."
The program src/real_minitalk.c has both the client and server code for a two-person talk program. It is very much like th_telnet, except it has code for setting up the server, and it doesn't print the "Read" like like th_telnet. What you should notice is that it's ok for one of the two programs to type lots of input, and it works fine. That's because each program has two threads -- one to handle standard input, and one to handle the thread.
UNIX> bin/real_minitalk localhost 5555 c Hi I said Hi Why aren't you talking to me? Is it because I am overbearing? No. Bye UNIX> |
UNIX> bin/real_minitalk localhost 5555 s Hi I said Hi Why aren't you talking to me? Is it because I am overbearing? No. Bye UNIX> |