THE CS435 CLASS LIBRARY by Edward McDowell, Rhode Island College The CS435 class library provides Java-like classes for threads and network input/output for Visual C++ Win32 console applications. These classes are sufficient for writing the programming projects for CS435, but may not be rich enough for commercial applications. This distribution is open source and may be freely modified and distributed. The distribution consists of five files: CS435.TXT This documentation file. THREAD.CPP Source code for thread library. THREAD.H Include file for thread library. SOCKET.CPP Source code for network library. SOCKET.H Include file for network library. These libraries are independent of one another and may be used together or separately. To use the libraries, include the appropriate source and header files in your Win32 console application. If you should link your program with the multi-threaded dynamic library. Specify the /MD option on the CL command line or select the Visual Studio project option "C/C++:Code Generation: Runtime Library:Multi-threaded DLL." If you use the network library you will need to link your program with the Windows library WSOCK32.LIB. Specify this library explicitly on the CL command line or in the "Additional Options" box of the Visual Studio project option "Linker:Command Line." LIBRARY OVERVIEW The thread library defines the following classes: Thread Represents a user-defined thread. Create a subclass of Thread and override the run() method to specify the code to be executed by the thread. The parent thread creates the thread object and then invokes its start() method. The run() method is then executed automatically in the new thread. Semaphore Provides semaphores for low-level thread synchronization. Additional functions provide mutual exclusion for critical sections and thread synchronization through wait() loops. The network library provides communication through TCP/IP client and server sockets. The following classes are defined: Socket A TCP/IP client socket. ServerSocket A TCP/IP server socket. THREAD.H The Thread class provides Java-like threads for Visual C++. Each thread is represented by an object of a subclass of class Thread. The run method is overriden to specify the code executed by the thread. A constructor may be provided to initialize the thread object with any data needed for its execution. The parent thread should create the thread object and then execute its start method to begin execution of the new thread. The run method of the thread object will be executed automatically in the new thread. (The parent thread must not call run directly. That would execute the run method in the parent thread, not in the new thread.) The Thread class is defined in the header file "thread.h" and has the following public methods. Thread::Thread() Constructs the thread object. Your subclass should provide a constructor to do any initialization required by your thread. Thread::~Thread() A do-nothing virtual destructor. It ensures that any destructor you provide in your subclass is executed. int Thread::getId() Returns the Windows thread id associated with the thread. This is the id returned by the threadId function while the thread is running. bool Thread::isAlive() Returns true if the thread has not yet completed. A thread completes when it returns from its run method. void Thread::join() This method may be invoked by another thread to wait for this thread to complete. void Thread::run() This do-nothing method must be overriden in your subclass to provide the code executed by your thread. Never call this method directly. It will be called in the new thread after the parent thread calls the start method. void Thread::start() This method must be called from the parent thread after the thread object has been constructed. The new thread will not execute until this method is called. It's purpose is to ensure that the new thread is not executed until all necessary initialization has been performed. The following functions provide mutual exclusion and thread synchronization. They are defined in "thread.h" but are not members of the Thread class. void lock() Enters a critical section by acquiring the lock. If another thread holds the lock then the current thread is blocked until the lock is available. At most one thread may hold the lock at any time. void unlock() Leaves a critical section by releasing the lock. void wait() Yields control to other threads from within a critical section. Wait releases the lock, yields control to other threads, and then reacquires the lock. void yield() Yields control to other threads without releasing the lock. int threadId() Returns the Windows thread id of the thread that is currently executing. void sleep(int milliseconds) Puts the thread that is currently executing to sleep for the specified number of milliseconds. void joinAll() Call this at the end of the main function to prevent program termination until all the threads that you have created have returned. A count is incremented each time a new thread is created. The count is decremented each time a thread completes. This function blocks until the count is zero. The Semaphore class provides semaphores for thread synchronization. Each semaphore encapsulates a nonnegative count. The initial value of the count is specified when the semaphore is created. A thread may acquire the semaphore when the count is positive. Acquiring the semaphore decrements the count. If a thread tries to acquire the semaphore when the count is zero the thread is blocked until the semaphore becomes positive. A thread may release the semaphore to increment its count. If the count is zero, this will allow a blocked thread to acquire the semaphore. Semaphores are provided by most operating systems for low-level process synchronization. They can be hard to use for application programming. The Semaphore class is defined in the "thread.h" header file. The following methods are provided. Semaphore::Semaphore(unsigned init) The constructor creates a new semaphore. The argument specifies the initial value of the count. void Semaphore::acquire() This method is invoked by a thread to acquire the semaphore. The thread is blocked until the count is positive. The count is then decremented. void Semaphore::release() { This method is invoked by a thread to increment the semaphore count. If the count is zero, this will allow a blocked thread to acquire the semaphore. SOCKET.H The Socket and ServerSocket classes provide network communication using TCP/IP reliable stream connections. The Socket class provides a client socket connection to a remote server. The ServerSocket class provides a server socket that accepts client connections on a specified port. These classes are similar to their Java namesakes. Both classes are defined in the header file "socket.h". The following function returns the dotted-quad IP address of the specified domain name. It returns the empty string if no match is found. string dnsLookup(string host) The Socket class represents a client socket connection. The following public methods are provided. Socket::Socket(string ipaddr, int port) The Socket constructor establishes a connection to the specified server and port. The first argument is a string giving the dotted-quad IP address of the server. Pass the string returned by the dnsLookup function described above, or "localhost" to specify the local node. The second argument is an int specifying the server port number. bool Socket::isOpen() This method returns true if the socket connection is open. It should be called after constructing the Socket object to determine whether the connection was established. void Socket::close() This method closes the socket connection. Data may not be read from or written to the socket after it has been closed. Every socket should be closed when it is no longer needed. string Socket::getAddress() int Socket::getPort() These methods return the IP address and port number of the remote node on the other end of the connection. string Socket::getLocalAddress() { int Socket::getLocalPort() { These methods return the IP address and port number of the local node. The following methods provide text-oriented output over the socket. The output stream is automatically flushed at the end of each line of output. void Socket::put(int ch) Write the specified character to the socket. The output stream is automatically flushed when '\n' is written. Use socket.put(' ') to insert spaces between words of output. Spaces are not inserted between items automatically. void Socket::print(string str) void Socket::print(int val) void Socket::print(long val) void Socket::print(double val) The print methods convert the specified items to string form and then write the string to the socket. void Socket::println() void Socket::println(string str) void Socket::println(int val) void Socket::println(long val) void Socket::println(double val) The println methods convert the specified items to string form, write the string to the socket, advance to a new line, and flush the output stream. The following methods provide text-oriented input from the socket. The input stream is organized as lines of text. Each line may contain zero or more words separated by white space (spaces and tabs). string Socket::nextLine() Reads the remainder of the input line as a string. The input position is advanced to the beginning of the next line. string Socket::next() int Socket::nextInt() long Socket::nextLong() double Socket::nextDouble() Reads the next word of input as the specified type. Words are separated in the input stream by white space. bool Socket::hasNext() Returns true if there are more words in the input stream. The input position is advanced to the beginning of the next word. bool Socket::more() Returns true if there are more characters in the input stream. The input position is not advanced. int Socket::get() Returns the ordinal of the current character and advances the input position to the next character. -1 is returned at the end of the input stream. int Socket::peek() Returns the ordinal of the current character but does not advance the input position. The next call to get or peek will return the same character. The following methods provide raw binary output over the socket. The output stream is never flushed unless the output buffer is full or the user calls the flush method explicitly. void Socket::write(int ch) Moves the low-order byte of the argument to the output buffer. The output will not be written until the output buffer is full or the socket is flushed. void Socket::flush() Writes all data in the output buffer to the remote node. The user must call flush explicitly and the end of each message or data will not be sent to the remote node. The following method provides raw binary input from the socket. int Socket::read() Returns the next byte of input as a positive integer. -1 is returned at the end of the input stream. The ServerSocket class represents a server socket that accepts client connections. The following public methods are provided. ServerSocket::ServerSocket(int port) The constructor creates a new server socket that accepts client connections on the specified port. bool ServerSocket::isOpen() This method returns true if the server socket was successfully created. Socket *ServerSocket::accept() This method waits for an incoming client connection. When a connection is established, it returns a pointer to a Socket object which can be used to communicate with the client. void ServerSocket::close() This method closes the server socket when it is no longer needed.