140 likes | 278 Views
Project Overview- TCP360. You need to implement a restricted version of TCP 3 Way Handshake Graceful connection termination Send & Receive buffer Sliding window protocol Reliable transmission lost packets corrupt packets out of order packets duplicate packets
E N D
Project Overview- TCP360 • You need to implement a restricted version of TCP • 3 Way Handshake • Graceful connection termination • Send & Receive buffer • Sliding window protocol • Reliable transmission • lost packets • corrupt packets • out of order packets • duplicate packets • You DO NOT need to implement • Persistence timers • Fast retransmit • Congestion control • Estimation of RTT or D • Nagle/fixes for silly window syndrome • TCP Options Your server and client will run on top of this new Transport Layer. You must support multiple TCP360 connections at once (think about your server) I will also give you another application (FTP) to stress test your TCP360
Project • The key here is DESIGN! • how many threads do you have? • where is your data? • Plan your implementation very carefully • To help you along this project will be made of smaller assignments due on a weekly basis! • I will provide you a basic design and some code!
Design Overview (10000 meters) Application Client Server Application sock = TCP360socket() TCP360Listen(sock, 99...) rSock = TCP360accept(sock, 99 TCP360recv(rSock, data ...) sock = TCP360socket() TCP360connect(sock,...,99) TCP360send(sock, data ...) TCP360 TCP360 Logical TCP360 Connection SendToTCPConn(data,...) TCP360 port:98 TCP360 port:99 NetworkLayerSend(data, IPAddr ...) NetworkLayer UDP port:9000 NetworkLayer UDP port:10001 udpSock = socket() bind(udpSock, myUDPport) recvfrom(udpSock, data, 9000,.. sendDataToTCP(data) UDP udpSock = socket() sendto(udpSock, data, 9000, IPAddr ...)
Design Overview (1 meter) Me You TCP360Connection TCP360Connection MessageQueue MessageQueue NetworkLayer Timer Alarm TCP data TCP data TCP data createAlarm() MessageQueue recvfrom() TCP360
Your First Assignment • Thread-safe Queue - Due April 6! • What is a queue? What is a thread safe data structure? • You need to provide a thread-safe queue to be used for the message passing • to make this general, the queue will store void* items • I will give you a .h file with function prototypes you must implement • Project description and .h file will be on the web page tomorrow • Watch the CS message boards for announcements! • you may NOT change the .h file, EXCEPT to add mutex variables • You must provide TWO test cases that show your queue works properly in a multithread environment • Due at 6PM! April 6!
Design Docs • Design is key! • Also due on April 6: A short design document for TCP360 • How many threads? • What will each do? • Where will the data be stored? • Who handles retransmits? • The full TCP360 project description will be posted by April 2 • You will need to schedule an individual meeting with me to discuss your design (April 6-9)
Thread-Safe Queue struct QueueItem{ void *data; // a pointer to the data int len; // the length of the memory allocated above struct QueueItem *next; // the next item in the queue struct QueueItem *prev; // the previous item in the queue }; struct Queue{ struct QueueItem *head; // read data from here struct QueueItem *tail; // push data in here // add pthreads data here };
Thread-Safe Queue /* * Allocate a queue struct and initialize its data members */ struct Queue* queueInit(); /* * Add the data to the queue * This method should dynamically allocate memory to store the * data in the queue. The data passed in by the user should * NOT be directly stored in the queue. * * queue is the Queue were this data will be added * data is a pointer to the data to be added * len is the length of the data to be added * * return 1 on success, 0 on error */ int queueEnqueue(struct Queue *queue, void *data, int len); // Why might queueEnqueue fail?
Thread-Safe Queue /* * Remove data from the queue * This method should return a pointer to the data element at * the head of the queue. It is the USER'S responsibility to * deallocate this memory. This function should deallocate the * QueueItem. * * queue is the Queue * len is the length of the data that is returned * timeout denotes how long to wait if the queue is empty. This * is given in milliseconds. -1 means block forever. * * return a pointer to the data on success, NULL on error */ void* queueDequeue(struct Queue *queue, int *len, int timeout); /* * Deallocate the queue and all the data it holds. * * queue is the Queue */ void queueDestory(struct Queue *queue);
Thread-Safe Queue /* * Return the data item at the head of the queue but DO NOT * remove it from the queue. This is similar to top() when * using a stack. * * queue is the Queue * len is the length of the data returned * * return a pointer to the data on success, NULL if the queue * is empty */ void* queueHead(struct Queue *queue, int *len); /* * Return 1 if the queue contains data, 0 if the queue is empty. * * queue is the Queue */ int queueProbe(struct Queue *queue);
Sample Usage void* foo(void *arg) { struct Queue* q = (struct Queue*) arg; int value = 42; int *retVal; int len; queueEnqueue(q, &value, sizeof(int)); value = 1138; queueEnqueue(q, &value, sizeof(int)); while( queueProbe(q) ) { retVal = (int*) queueDequeue(q, &len, QUEUE_BLOCK); fprintf(stderr," VALUE: %d \n”, *retVal); free(retVal); } return NULL ; }
Sample Usage void bar() { struct Queue * q = queueInit(); pthread_t t1, t2, t3; pthread_create(&t1, NULL, foo, (void*) q); pthread_create(&t2, NULL, foo, (void*) q); pthread_create(&t3, NULL, foo, (void*) q); pthread_join(t1, NULL); pthread_join(t2, NULL); pthread_join(t3, NULL); queueDestroy(q); } // What will the output be?
pthread_cond_t waitblock; pthread_mutex_t valueMutex; int value=0; void* setValue(void* arg) { pthread_mutex_lock(&valueMutex); sleep(LONGTIME); value = *(int*)arg; pthread_mutex_unlock(&valueMutex); pthread_cond_signal(&waitBlock); } Timed Wait int main() { pthread_t t1, t2; int timeout = 2500; pthread_mutex_init(&valueMutex, NULL); pthread_cond_init(&waitBlock, NULL); pthread_create(&t1, NULL, setValue, (void*) &timeout ); pthread_create(&t2, NULL, printValue, (void*) &timeout); pthread_join(t1, NULL); pthread_join(t2, NULL);
#include <time.h> #include <sys/time.h> void* printValue(void* arg) { int timeout = *(int*) arg; // timeout is in milliseconds! struct timespec realtime; int retVal; pthread_mutex_lock(&valueMutex); // acquire mutex! if( value == 0 ) // has value been set? { // Not set clock_gettime(CLOCK_REALTIME,&realtime); // use -lrt to link! realtime.tv_nsec += 1000000*(timeout % 1000); realtime.tv_nsec %= 1000000000;// don't overflow nsec! realtime.tv_sec += timeout / 1000; pthread_cond_timedwait(&waitblock, &valueMutex, &realtime); } retVal = value; pthread_mutex_unlock(&valueMutex); fprintf(stderr ”Value: %d\n”, retVal); Timed Wait