SOFT3410 Tutorial 11 Task Parallelism
Question 1: Simple FTP – Case Study
For this task, you are required to construct a simple FTP server that handle a small set of operations (retrieving and uploading files). The below is a list of commands clients can send to your server.
• LIST – Gets the list of files and directories at the root of the server
• RETR
• STOR
• DELE
• RNFR
• RNTO
• SIZE
• QUIT – Closes the connection
On top of implementing the above protocol, your program should accept the following command line arguments.
./ftpserver :PORT :DIRECTORY
./ftpserver 9001 ./myfiles
The above :PORT should specify the port the network port the application will listen on. The directory will be the folder that will be served to the clients.
The above specifies enough commands to run a simple FTP server in anonymouse mode. However, we need to test out server. Use the command nc or netcat to connect to your server and run the commands specified.
You can use the following scaffold to help get started.
uint32_t addrlen = sizeof(struct sockaddr_in); clientsocket_fd = accept(serversocket_fd,
(struct sockaddr*) &address, &addrlen); read(clientsocket_fd, buffer, 1024); puts(buffer);
close(clientsocket_fd);
SOFT3410 Task Parallelism
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char** argv) { int serversocket_fd = -1;
int clientsocket_fd = -1;
int port = 9000;
struct sockaddr_in address; int option = 1;
char buffer[1024];
serversocket_fd = socket(AF_INET, SOCK_STREAM, 0);
if(serversocket_fd < 0) { puts("This failed!");
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(port);
setsockopt(serversocket_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &option, sizeof(int));
if(bind(serversocket_fd, (struct sockaddr*) &address, sizeof(struct sockaddr_in))) {
listen(serversocket_fd, 1024); while(1) {
Concurrency
Page 2 of 4
close(serversocket_fd); return 0;
Question 2: Using threads
Instead of handling each connection synchronously, spawn a thread or use a thread pool to handle multiple connections at once. Ensure that each thread has a property the main thread can see to check if the thread has finished. This will allow the main thread to rejoin threads that have finished their work.
Question 3: Are threads always the answer?
Modify your original server to use the poll call. Instead of using multiple threads to process con- nections asynchronously, the poll function and a file descriptor set can be use to monitor events on the sockets.
Monitor each file descriptor with POLLIN and POLLHUP. POLLIN events are generated when a file descriptor has data.
struct pollfd fds[3];
size_t nfds = 3;
// Set each file descriptor
//fds[i].fd = fd;
//fds[i].events = POLLIN | POLLHUP;
// Maybe change the file descriptor to use non-blocking
while(poll(fds, nfds, -1) >= 0) { for(size_t i = 0; i < nfds; i++) {
if(fds[i].revents & POLLIN) {
//What to do if POLLIN was received on //this file descriptor
//event loop to check
SOFT3410 Task Parallelism
Concurrency
Page 3 of 4
Question 4: Timing your ftp server
By now, you should have three variants of your ftp server. You will need to time each of these servers and find how well these servers perform under certain workloads.
• Single connection - Synchronous
• Multi-threaded - Thread
• Single-Threaded - Event-Driven IO
Construct a few different workloads to test these your servers. Restricted the number of cores these webservers have access to by using taskset.
Review and discuss the C10K Problem.
SOFT3410 Task Parallelism
Concurrency Page 4 of 4