Due: Monday, September 8th, 2008 10:45am
Submit two programs (server and client) on a CADE machine using
handin cs4960-01 hw2 <file1> <file2>
HW1 was about parallelism on a shared-memory environment. HW2 is about parallism in a message-passing environment. There is no Java option for HW2.
Your task is to implement a server and a client program. Two copies of server will run, and one copy of client will run. The servers are told a TCP port to listen on, and the client is given the addresses and ports of the two server:
./server 40001 &
./server 40002 &
time ./client localhost 40001 locahost 40002
The client should print the same result as the old hw1.c program with deconvert changed to call convert, but it farms out the work to the two servers, so it should produce a result twice as fast. The locahost above assumes that the clients are running on the same machines, but you can run clients on different machines, too.
(It might seem backward to have multiple servers and one client, but this arrangement makes it easy to start the servers first and then time the computation at the client.)
Start with the following files:
hw1.c—
extract useful code from here; you won't need popp_thread.h. Your server program must use convert without changing it, of course.
msg.c and msg.h—
this is a library for message-passing communication, where all messages are arrays of integers. The API is as follows:
struct connection_t *wait_for_connection(char *portno)
Called by a server to listen (at a given port number) for a connection from a client. The connection is returned when it's ready.
struct connection_t *make_connection(char *host, char *portno)
Called by a client to connect to a server (at a given host and port number). The new connection is returned.
int send_message(struct connection_t *c, int len, int *msg)
Sends an array to the other end of the connection. The result is always len.
int recv_message(struct connection_t *c, int len, int *msg)
Sends an array to the other end of the connection. The result is always len.
void close_connection(struct connection_t *c)
Closes a connection.
Once a connection is established, send_message and recv_message can be used any number of times on the connection, as long as a send on one end is matched by a recv on the other end of the connection (for the same amount of data). A connection can buffer a small amount of data, but sending blocks when the buffer is full, so that sending mostly blocks until data is receieved. A recv blocks until all of the requested data is received. When an error occurs with any of the above functions, a message is printed to stderr and the program aborts.
To help you get started with the message libraries, here are some extra files:
client.c—
a sample client
server.c—
a sample server
msg_test.h—
configuration used by the samples
Compile them something like this:
gcc -o server -O2 -Wall server.c msg.c
gcc -o client -O2 -Wall client.c msg.c
Then run them like this, each in a different terminal window on the same machine:
./server 40001
./client localhost 40001
The server should print 0 through 4, as sent to it by the client. The client should print 100, as sent back to it by the server.
Make your server work with an arbitrary number of clients, as determined by the number of command-line arguments supplied to it. Using multiple machines in the CADE lab, you should be able to get speedups greater than a factor of 2.
Last update: Monday, December 1st, 2008mflatt@cs.utah.edu |