You are on page 1of 29

COMP ENG 4DN4

Lab 3 Report
(MacTella Peer-to-Peer System)

Submitted by:
Gagandeep Chambal – 0541763
Rohan Thivy – 0461139
Introduction:

In this lab, we changed the FTP-based application (McNapster) developed in lab


2 to develop a peer to peer system which where each peer acts as both a client
and a server to exchange data and there is no centralized server which acts as a
single critical resource. The Mactella version we implemented in this lab will
support the following features: a distributed search engine, distributed file
sharing, and a decentralized network topology.

QuickTime™ and a
decompressor
are needed to see this picture.

Mactella Commands
Command Description
LIST Lists the shared files in the host’s current
directory.
LISTR <ip_address> Lists the shared files in remote peer
<port_number> specified by ip address and port number
SEARCH <fileName > <TTL> Sends a request to other peers with the
specified TTL (integer value).
The search results are printed on screen
with <ip address> and <port number> of
each peer that has the file.
DISCOVER <depth> Updates the list of active hosts and
displays them up to a certain depth
specified by <depth>
GET <filename> <ip_address> Retrieves the file from the peer specified
<port_number> by the ip address and port number
QUIT Exits from the host Mactella peer
Program Flowcharts

Client Connection

Start

Create Control
Socket

Connect to
Server

Send Data Port Number


via control stack

Create Data
Socket

Connect Data
Port

END
LIST/LISTR COMMAND

START

Get IP add, Port


Num

If IP address = NULL

Assign Client IP Assign Host IP

Open Directory

List Directory
Contents

END
DISCOVER COMMAND
START

Get Depth

Create Discover
Port

Create Discover
Get Packet
Packet

Get Peer IP Add


NO
YES If Depth is > 0
If Peer IP is NULL
End YES
NO
Listen()
Connect to IP with
Disconnect
port 6020
Create Thread
Transfer Packets

Receive Discover
Packets
Disconnect

Get IP and Depth

YES

IP already
Close Thread
encountered

NO

Add IP to Peer IP
list

Close Thread
GET COMMAND

Start

Create Control
Socket

Connect to
Server

Send Data Port Number


via control stack

Create Data
Socket

Connect Data
Port

Send Control
Packet

Receive File via


Data Socket

Close connection

END
Source Code:

Accept TCP Connection:


#include <stdio.h> /* for printf(), fprintf() */
#include <winsock.h> /* for socket(),... */

void DieWithError(char *errorMessage); /* Error handling function */

int AcceptTCPConnection(int servSock)


{
int clntSock; /* Socket descriptor for client */
struct sockaddr_in echoClntAddr; /* Client address */
unsigned int clntLen; /* Length of client address data structure */

/* Set the size of the in-out parameter */


clntLen = sizeof(echoClntAddr);

/* Wait for a client to connect */


if ((clntSock = accept(servSock, (struct sockaddr *) &echoClntAddr, &clntLen)) < 0)
DieWithError("Server closed");

/* clntSock is connected to a client! */

printf("\nHandling client %s\n", inet_ntoa(echoClntAddr.sin_addr));

return clntSock;
}

Create TCP Server Socket:


#include <winsock.h> /* for socket(),... */

#define MAXPENDING 5 /* Maximum outstanding connection requests */

void DieWithError(char *errorMessage); /* Error handling function */

int CreateTCPServerSocket(int port)


{
int sock; /* socket to create */
struct sockaddr_in echoServAddr; /* Local address */

/* Create socket for incoming connections */


if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
printf("created sock--: %d\n",port);
/* Construct local address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(port); /* Local port */

/* Bind to the local address */


if (bind(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");

/* Mark the socket so it will listen for incoming connections */


if (listen(sock, MAXPENDING) < 0)
DieWithError("listen() failed");

return sock;
}
Handle TCP Client:
#include <winsock2.h> /* for socket(),... */
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define RCVBUFSIZE 125 /* Size of receive buffer */
#define MESSAGESIZEMAX 125

#define MAXPENDING 50

char LISTFILE[100],LIST[100];

void DieWithError(char *errorMessage); /* Error handling function */


int getSize(char *file); //get the file size

void HandleTCPClient(int clntSocket,int localPort,int directory, int *flag, int


knownPort, char knownIP[100])
{
FILE *ufp;
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
int recvMsgSize; /* Size of received message */
int echoServPort1;
int clntdataSocket1;
int dataPort;
int dataPortLength;
int dataSocket;
int clntDataSocket;
int commandSize;
int messageSize;
int filefound=0;
int sock1; /* Socket descriptor */
int byteSent;
int ip_addrSize;
int port_number;
int getTypeSize;
int fileSize;
int ttl;
int depth;
int check= 0;
int totByteSent;
int totByteReceived;
int bytesReceived;
int rcv;
int totalBytesRcvd;
int echoStringLen;
int echoStringLenlength;
int portNumber;
int portNumberLength;
int rcvMsgSize;

struct sockaddr_in echoServAddr;


struct sockaddr_in echoClntAddr;
struct sockaddr_in dataEchoServAddr1;
struct sockaddr_in echoServAddr1;

char messageSizeChar[MESSAGESIZEMAX];
char message[MESSAGESIZEMAX];
char command[100];
char file[100];
char fileName[100];
char downloadDirectory[150];
char fileDirectory[150];
char discovered[100];
char searched[100];
char localIP[100] = "127.0.0.1";
char ip_addr[100];
int flagttl=0;
int clntLen;
int transmissionSize;
int transmissionStringSize;

strcpy(LISTFILE,directory);
strcat(LISTFILE,"\\");
strcpy(LIST,LISTFILE);
strcat(LIST,"List.txt");

strcpy(downloadDirectory,directory);

/* Receive message from client */


memset(&echoBuffer, 0, sizeof(echoBuffer));
if ((recvMsgSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) < 0)
DieWithError("recv() failed");

echoBuffer[recvMsgSize] = '\0';

if (strstr(echoBuffer,"NOT") != NULL){
check = 1;
dataPort = atoi(&echoBuffer[3]);
}
else{

dataPort = atoi(echoBuffer);
messageSize = sprintf(message,"----Welcome to MacTella-----\nOPTIONS--\n1)
LIST \n2) LISTR \n3) SEARCH \n4) DISCOVER\n5) GET\n6) QUIT\n\n");
sprintf(messageSizeChar,"%d",messageSize);

if (send(clntSocket, messageSizeChar, messageSize, 0) != messageSize)


DieWithError("send() failed");

if (send(clntSocket, message, messageSize, 0) != messageSize)


DieWithError("send() failed");
}
if ((dataSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

memset(&echoServAddr,0,sizeof(echoServAddr));
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(dataPort);

if (bind(dataSocket,(struct sockaddr *)&echoServAddr, sizeof(echoServAddr)) < 0)


DieWithError("bind() failed");

if (listen(dataSocket,MAXPENDING) < 0)
DieWithError("listen() failed");

clntLen = sizeof(echoClntAddr);
if ((clntDataSocket = accept(dataSocket, (struct sockaddr
*)&echoClntAddr,&clntLen)) < 0)
DieWithError("accept() failed");

printf("Waiting for client command...\n");


memset(&echoBuffer,0,sizeof(echoBuffer));
if (commandSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0) <= 0)
DieWithError("recv() failed");

strcpy(command,echoBuffer);
while(strcmp(command,"QUIT")!=0)
{
if(strcmp(command,"LIST") == 0)
{
printf("\nSending List...\n\n");

transmissionSize = getSize(LIST);
transmissionStringSize = sprintf(echoBuffer, "%d",
transmissionSize);

if (send(clntDataSocket, echoBuffer, transmissionStringSize, 0) !=


transmissionStringSize)
DieWithError("send() failed");

if ((ufp = fopen(LIST,"rb")) == NULL)


printf("Cannot read File");

byteSent=0;

while(!feof(ufp))
{
transmissionSize = fread(echoBuffer,
sizeof(char),RCVBUFSIZE,ufp);

if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !


= transmissionSize)
DieWithError("send() failed");

echoBuffer[transmissionSize]='\0';
printf("%s",echoBuffer);
}
fclose(ufp);
}
else if (strcmp(command,"SEARCH") == 0){

memset(&echoBuffer, 0, sizeof(echoBuffer));
if ((getTypeSize = recv(clntSocket,echoBuffer, RCVBUFSIZE - 1,0))
<= 0)
DieWithError("recv() failed");

echoBuffer[getTypeSize] = '\0';
strcpy(fileName,echoBuffer);

strcat(LISTFILE,fileName);

memset(&echoBuffer,0,sizeof(echoBuffer));
if ((getTypeSize = recv(clntSocket,echoBuffer, RCVBUFSIZE - 1,0))
<= 0)
DieWithError("recv() failed");
echoBuffer[getTypeSize] = '\0';
ttl = atoi(echoBuffer);

if ((ufp = fopen (LISTFILE,"rb")) == NULL){

ttl--;
if (ttl == 0){

messageSize = sprintf(message,"Cannot Find File");


sprintf(messageSizeChar,"%d",messageSize);

if (send(clntSocket, message, messageSize, 0) !=


messageSize)
DieWithError("send() failed");
}
else{

/* Create a reliable, stream socket using TCP */


if ((sock1 = socket(PF_INET, SOCK_STREAM,
IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

/* Construct the server address structure */


memset(&echoServAddr1, 0, sizeof(echoServAddr1));
/* Zero out structure */
echoServAddr1.sin_family = AF_INET;
/* Internet address family */
echoServAddr1.sin_addr.s_addr = inet_addr(knownIP);
/* Server IP address */
echoServAddr1.sin_port = htons(knownPort); /*
Server port */
/* Establish the connection to the echo server */
if (connect(sock1, (struct sockaddr *)
&echoServAddr1, sizeof(echoServAddr1)) < 0)
DieWithError("connect() failed");

totalBytesRcvd = 0;
memset(&command, 0, sizeof(command));
strcpy(command,"NOT");
echoStringLen = strlen(command);
if (send(sock1, command, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

srand(time(NULL));
memset(&echoBuffer, 0, sizeof(echoBuffer));
sprintf(echoBuffer,"%d",rand()%99999);
echoStringLen = strlen(echoBuffer); /*
Determine input length */
portNumber = atoi(echoBuffer);

/* Send the string, including the null terminator,


to the server */
if (send(sock1, echoBuffer, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

if ((clntdataSocket1 = socket(PF_INET, SOCK_STREAM,


IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

memset(&dataEchoServAddr1, 0,
sizeof(dataEchoServAddr1)); /* Zero out structure */
dataEchoServAddr1.sin_family = AF_INET;
/* Internet address family */
dataEchoServAddr1.sin_addr.s_addr =
inet_addr(knownIP); /* Server IP address */
dataEchoServAddr1.sin_port =
htons(portNumber); /* Server port */
if (connect(clntdataSocket1, (struct sockaddr *)
&dataEchoServAddr1, sizeof(dataEchoServAddr1)) < 0)
DieWithError("connect() client failed");

memset(&command, 0, sizeof(command));
strcpy(command,"SEARCH");
echoStringLen = strlen(command);
if (send(sock1, command, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

echoStringLen = strlen(fileName);
Sleep(200);
memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,fileName);
echoStringLen = strlen(echoBuffer);
if (send(sock1,echoBuffer,echoStringLen,0) !=
echoStringLen)
DieWithError("send() failed");

Sleep(200);
memset(&command,0,sizeof(command));
sprintf(command,"%d",ttl);
echoStringLen = strlen(command);
if (send(sock1,command,echoStringLen,0) !=
echoStringLen)
DieWithError("send() failed");

if ((rcvMsgSize = recv(clntdataSocket1, echoBuffer,


RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");
echoBuffer[rcvMsgSize]='\0';

if (strcmp(echoBuffer,"Cannot Find File") == 0){

if (send(clntSocket,echoBuffer,rcvMsgSize,0)
!= rcvMsgSize)
DieWithError("send() failed");
}
else{
flagttl=1;
strcpy(ip_addr,echoBuffer);

if ((rcvMsgSize = recv(clntdataSocket1,
echoBuffer, RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");

echoBuffer[rcvMsgSize]='\0';
port_number = atoi(echoBuffer);

}
}else
filefound=1;
if((check == 1)&&(filefound == 1)){

memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,localIP);
transmissionSize = strlen(echoBuffer);
Sleep(1000);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

memset(&echoBuffer,0,sizeof(echoBuffer));
sprintf(echoBuffer,"%d",localPort);
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

}
else if (filefound == 1){

memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,localIP);
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

memset(&echoBuffer,0,sizeof(echoBuffer));
sprintf(echoBuffer,"%d",localPort);
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");
}
else if(flagttl==0){

memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,"Cannot Find File");
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

}
else
{
memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,ip_addr);
transmissionSize = strlen(echoBuffer);
Sleep(1000);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

memset(&echoBuffer,0,sizeof(echoBuffer));
sprintf(echoBuffer,"%d",port_number);
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !
= transmissionSize)
DieWithError("send() failed");

}
closesocket(sock1);
closesocket(clntdataSocket1);
if(filefound)
fclose(ufp);
}

else if (strcmp(command,"DISCOVER") == 0){


memset(&discovered,0,sizeof(discovered));
memset(&echoBuffer,0,sizeof(echoBuffer));
if ((getTypeSize = recv(clntSocket,echoBuffer, RCVBUFSIZE - 1,0))
<= 0)
DieWithError("recv() failed");
echoBuffer[getTypeSize] = '\0';
depth = atoi(echoBuffer);
depth--;
if (depth != 0){
/* Create a reliable, stream socket using TCP */
if ((sock1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

/* Construct the server address structure */


memset(&echoServAddr1, 0, sizeof(echoServAddr1)); /*
Zero out structure */
echoServAddr1.sin_family = AF_INET; /*
Internet address family */
echoServAddr1.sin_addr.s_addr = inet_addr(knownIP); /*
Server IP address */
echoServAddr1.sin_port = htons(knownPort); /* Server
port */
/* Establish the connection to the echo server */
if (connect(sock1, (struct sockaddr *) &echoServAddr1,
sizeof(echoServAddr1)) < 0){
}
else{

totalBytesRcvd = 0;
memset(&command, 0, sizeof(command));
strcpy(command,"NOT");
echoStringLen = strlen(command);
if (send(sock1, command, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

srand(time(NULL));
memset(&echoBuffer, 0, sizeof(echoBuffer));
sprintf(echoBuffer,"%d",rand()%99999);
echoStringLen = strlen(echoBuffer); /*
Determine input length */
portNumber = atoi(echoBuffer);

/* Send the string, including the null terminator,


to the server */
if (send(sock1, echoBuffer, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

if ((clntdataSocket1 = socket(PF_INET, SOCK_STREAM,


IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

memset(&dataEchoServAddr1, 0,
sizeof(dataEchoServAddr1)); /* Zero out structure */
dataEchoServAddr1.sin_family = AF_INET;
/* Internet address family */
dataEchoServAddr1.sin_addr.s_addr =
inet_addr(knownIP); /* Server IP address */
dataEchoServAddr1.sin_port =
htons(portNumber); /* Server port */
if (connect(clntdataSocket1, (struct sockaddr *)
&dataEchoServAddr1, sizeof(dataEchoServAddr1)) < 0)
DieWithError("connect() client failed");

memset(&command, 0, sizeof(command));
strcpy(command,"DISCOVER");
echoStringLen = strlen(command);
Sleep(200);
if (send(sock1, command, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

Sleep(200);
memset(&command,0,sizeof(command));
sprintf(command,"%d",depth);
echoStringLen = strlen(command);
if (send(sock1,command,echoStringLen,0) !=
echoStringLen)
DieWithError("send() failed");

if ((rcvMsgSize = recv(clntdataSocket1, echoBuffer,


RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");

echoBuffer[rcvMsgSize]='\0';
strcat(discovered,echoBuffer);
strcat(discovered,"\n");

}
memset(&echoBuffer,0,sizeof(echoBuffer));
strcat(discovered,localIP);
strcat(discovered," ");
memset(&echoBuffer,0,sizeof(echoBuffer));
sprintf(echoBuffer,"%d",localPort);
strcat(discovered,echoBuffer);
strcat(discovered,"\n");
memset(&echoBuffer,0,sizeof(echoBuffer));
strcpy(echoBuffer,discovered);
transmissionSize = strlen(echoBuffer);
if (send(clntDataSocket, echoBuffer, transmissionSize, 0) !=
transmissionSize)
DieWithError("send() failed");
closesocket(sock1);
closesocket(clntdataSocket1);
}

else if (strcmp(command,"GET") == 0)
{
memset(&echoBuffer,0,sizeof(echoBuffer));
memset(&fileName,0,sizeof(fileName));
if ((fileSize = recv(clntSocket, echoBuffer, RCVBUFSIZE - 1, 0)) <=
0)
DieWithError("recv() failed");
echoBuffer[fileSize] = '\0';
strcpy(fileName,echoBuffer);

strcpy(fileDirectory,LISTFILE);
strcat(fileDirectory,fileName);

transmissionSize = getSize(fileDirectory);
transmissionStringSize = sprintf(echoBuffer, "%d",
transmissionSize);

if (send(clntDataSocket, echoBuffer, transmissionStringSize, 0) !=


transmissionStringSize)
DieWithError("send() failed");

if(transmissionSize != 0)
{
if ((ufp = fopen(fileDirectory,"rb")) == NULL)
printf("Cannot read File!\n");

byteSent = 0;
totByteSent = 0;
recv(clntSocket, echoBuffer, RCVBUFSIZE - 1, 0);

while(!feof(ufp))
{
transmissionSize = fread(echoBuffer, sizeof(char),
RCVBUFSIZE - 1, ufp);

echoBuffer[transmissionSize] = '\0';

if (byteSent = send(clntDataSocket, echoBuffer,


transmissionSize, 0) != transmissionSize)
DieWithError("send() failed");

totByteSent += byteSent;

}
fclose(ufp);
}
else
printf("File does not exist. Restart");
}

else
printf("Invalid command\n");

if (check == 1) break;
Sleep(100);
printf("Waiting for next client command...\n");

if ((commandSize = recv(clntSocket, echoBuffer, RCVBUFSIZE, 0)) <=


0)
DieWithError("recv() failed");

echoBuffer[commandSize] = '\0';
strcpy(command,echoBuffer);

}
if (check != 1) {
flag=0;
printf("Client has exited\n");
closesocket(clntSocket);
printf("Are you sure you want to Quit?\n");
gets(echoBuffer);
if (strcmp(echoBuffer,"Yes")==0){
closesocket(clntDataSocket);
WSACleanup();
*flag=1;
}
}
else{
closesocket(clntSocket);
}

int getSize(char *file) //function for getting file size


{
FILE *fileptr;
long fileSize=0;
if ((fileptr=fopen(file,"rb"))==NULL)
printf("Could not open the file %s\n",file);

else
{
fseek (fileptr , 0 , SEEK_END);

fileSize = ftell (fileptr);

rewind(fileptr);
fclose(fileptr);
}
return(fileSize);
}

TCP Echo Client:

#include <stdio.h> /* for printf(), fprintf() */


#include <winsock2.h> /* for socket(),... */
#include <stdlib.h> /* for exit() */
#include <windows.h>

#define RCVBUFSIZE 125 /* Size of receive buffer */

void DieWithError(char *errorMessage); /* Error handling function */


int getSize2(char *file);

struct ThreadArgs
{
int clntSock; /* Socket descriptor for client */
char directory[1000];
int knownPort;
char knownIP[100];
int flag;
int portnumber;
};
void *ThreadMain2(void *threadArgs);

void Main(int argc, char *argv[])


{
WSADATA wsaData; /* Structure for WinSock setup communication */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in echoServAddr1; /* Echo server address */
struct sockaddr_in dataEchoServAddr;
struct sockaddr_in dataEchoServAddr1;

int sock;
int echoServPort; /* Echo server port */
int sock1; /* Socket descriptor */
int echoServPort1; /* Echo server port */
int echoStringLen; /* Length of string to echo */
int bytesRcvd, totalBytesRcvd; /* Bytes read in single recv() and total bytes
read */
int rcvMsgSize;
int portNumber;
int portNumberLength;
int instructionSize;
int clntdataSocket;
int clntdataSocket1;
int totBytesReceived;
int transSize;
int transStringSize;
int bytesReceived;
int totByteSent;
int byteSent;
int port_number;

char fileName [100];


char downloadDirectory[150];
char listFile [100];
char *servIP; /* Server IP address (dotted quad) */
char *echoString; /* String to send to echo server */
char echoBuffer[RCVBUFSIZE]; /* Buffer for echo string */
char fileName1 [100];
char ttl[100];
char instructions[RCVBUFSIZE];
char command[15];
char depth[100];
char ip_addr[20];
char uploadFile[125];
char uploadDirectory[150];

FILE *ufp;
FILE *dfp;

DWORD threadID; /* Thread ID from CreateThread() */

if (argc!=5) /* Test for correct number of arguments */


{
fprintf(stderr, "%s <PORT> <DIRECTORY> <PEER_IP> <PEER_PORT>\n", argv[0]);
exit(1);
}

echoServPort = atoi(argv[1]); /* Use given port, if any */


servIP= argv[3];

if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */


{
fprintf(stderr, "WSAStartup() failed");
exit(1);
}

/* Create separate memory for client argument */


threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs));
threadArgs->portnumber =echoServPort;
strcpy(threadArgs -> directory, argv[2]);
threadArgs->knownPort = atoi(argv[4]);
strcpy(threadArgs->knownIP,argv[3]);
strcpy(rootDirectory,argv[2]);

// printf("port:%d",echoServPort);

if (CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadMain2, threadArgs,


0, (LPDWORD) &threadID) == NULL)
DieWithError("pthread_create() failed");

/* Create a reliable, stream socket using TCP */


if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

/* Construct the server address structure */


memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons(echoServPort); /* Server port */
/* Establish the connection to the echo server */
if (connect(sock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("connect() failed sdf");

totalBytesRcvd = 0;

srand(time(NULL));
sprintf(echoBuffer,"%d",rand()%9999);
echoStringLen = strlen(echoBuffer); /* Determine input length */
portNumber = atoi(echoBuffer);
portNumberLength = sizeof(portNumber);

/* Send the string, including the null terminator, to the server */


if (send(sock, echoBuffer, echoStringLen, 0) != echoStringLen)
DieWithError("send() failed");

if ((rcvMsgSize = recv(sock, echoBuffer, RCVBUFSIZE - 1, 0)) <= 0)


DieWithError("recv() failed or connection closed prematurely");

echoBuffer[rcvMsgSize] = '\0';
instructionSize = atoi(echoBuffer);

if ((rcvMsgSize = recv(sock, echoBuffer, instructionSize, 0)) <= 0)


DieWithError("recv() failed or connection closed prematurely");

echoBuffer[rcvMsgSize] = '\0';
strcpy(instructions,echoBuffer);
printf("%s",instructions);

if ((clntdataSocket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)


DieWithError("socket() failed");

memset(&dataEchoServAddr, 0, sizeof(dataEchoServAddr)); /* Zero out structure


*/
dataEchoServAddr.sin_family = AF_INET; /* Internet address family
*/
dataEchoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
dataEchoServAddr.sin_port = htons(portNumber); /* Server port */

if (connect(clntdataSocket, (struct sockaddr *) &dataEchoServAddr,


sizeof(dataEchoServAddr)) < 0)
DieWithError("connect() client failed");

gets(echoBuffer);
strcpy(command,echoBuffer);

echoStringLen = strlen(command);
if (strcmp(command,"LISTR") != 0){
if (send(sock, command, echoStringLen, 0) != echoStringLen)
DieWithError("send() failed");
}

while(strcmp(command,"QUIT") != 0)
{
if ((strcmp(command,"LIST") == 0)||(strcmp(command,"LISTR") == 0)||
(strcmp(command,"SEARCH") == 0)||(strcmp(command,"DISCOVER") == 0)||
(strcmp(command,"GET") == 0))
{
if ((strcmp(command,"LIST") == 0))
{
totBytesReceived = 0;
if ((rcvMsgSize = recv(clntdataSocket, echoBuffer,
RCVBUFSIZE, 0)) <= 0)
DieWithError("recv() failed");

echoBuffer[rcvMsgSize] = '\0';
transSize = atoi(echoBuffer);
while (totBytesReceived < transSize)
{
if ((bytesReceived = recv(clntdataSocket,
echoBuffer, RCVBUFSIZE, 0)) <= 0)
DieWithError("recv() failed");

totBytesReceived += bytesReceived;
echoBuffer[bytesReceived] = '\0';
}
}
else if (strcmp(command,"LISTR") == 0)
{
printf("\nPlease enter ip_address\n");
gets(echoBuffer);

printf("%s\n",echoBuffer);
strcpy(ip_addr,echoBuffer);
printf("%s\n",ip_addr);
echoStringLen = strlen(ip_addr);
printf("%s\n",ip_addr);

printf("\nPlease enter port_number\n");


gets(echoBuffer);

port_number = atoi(echoBuffer);

/* Create a reliable, stream socket using TCP */


if ((sock1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

/* Construct the server address structure */


memset(&echoServAddr1, 0, sizeof(echoServAddr1)); /*
Zero out structure */
echoServAddr1.sin_family = AF_INET; /*
Internet address family */
echoServAddr1.sin_addr.s_addr = inet_addr(ip_addr); /*
Server IP address */
echoServAddr1.sin_port = htons(port_number); /*
Server port */
/* Establish the connection to the echo server */
if (connect(sock1, (struct sockaddr *) &echoServAddr1,
sizeof(echoServAddr1)) < 0)
DieWithError("connect() failed sdf");

totalBytesRcvd = 0;

srand(time(NULL));
sprintf(echoBuffer,"%d",rand()%9999);
echoStringLen = strlen(echoBuffer); /* Determine
input length */
portNumber = atoi(echoBuffer);
portNumberLength = sizeof(portNumber);

/* Send the string, including the null terminator, to the


server */
if (send(sock1, echoBuffer, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

if ((rcvMsgSize = recv(sock1, echoBuffer, RCVBUFSIZE - 1,


0)) <= 0)
DieWithError("recv() failed or connection closed
prematurely");

echoBuffer[rcvMsgSize] = '\0';
instructionSize = atoi(echoBuffer);

if ((rcvMsgSize = recv(sock1, echoBuffer, instructionSize,


0)) <= 0)
DieWithError("recv() failed or connection closed
prematurely");

echoBuffer[rcvMsgSize] = '\0';
strcpy(instructions,echoBuffer);

if ((clntdataSocket1 = socket(PF_INET, SOCK_STREAM,


IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

memset(&dataEchoServAddr1, 0, sizeof(dataEchoServAddr1));
/* Zero out structure */
dataEchoServAddr1.sin_family = AF_INET; /*
Internet address family */
dataEchoServAddr1.sin_addr.s_addr = inet_addr(ip_addr);
/* Server IP address */
dataEchoServAddr1.sin_port = htons(portNumber); /*
Server port */

if (connect(clntdataSocket1, (struct sockaddr *)


&dataEchoServAddr1, sizeof(dataEchoServAddr1)) < 0)
DieWithError("connect() client failed");

strcpy(command,"LIST");

echoStringLen = strlen(command);

if (send(sock1, command, echoStringLen, 0) != echoStringLen)


DieWithError("send() failed");

totBytesReceived = 0;
if ((rcvMsgSize = recv(clntdataSocket1, echoBuffer,
RCVBUFSIZE, 0)) <= 0)
DieWithError("recv() failed");

echoBuffer[rcvMsgSize] = '\0';
transSize = atoi(echoBuffer);

while (totBytesReceived < transSize)


{
if ((bytesReceived = recv(clntdataSocket1,
echoBuffer, RCVBUFSIZE, 0)) <= 0)
DieWithError("recv() failed");

totBytesReceived += bytesReceived;
echoBuffer[bytesReceived] = '\0';
printf("\n%s\n",echoBuffer);
}
}
else if (strcmp(command,"SEARCH") == 0)
{
printf("\nPlease enter fileName\n");
gets(echoBuffer);
strcpy(fileName1,echoBuffer);

memset(&echoBuffer,0,sizeof(echoBuffer));
echoStringLen = strlen(fileName1);
sprintf(echoBuffer,"%d",echoStringLen);

strcpy(echoBuffer,fileName1);
if (send(sock,fileName1,echoStringLen,0) != echoStringLen)
DieWithError("send() failed");

printf("\nPlease enter TTL\n");


gets(echoBuffer);

strcpy(ttl,echoBuffer);
echoStringLen = strlen(ttl);

if (send(sock,ttl,echoStringLen,0) != echoStringLen)
DieWithError("send() failed");
memset(&echoBuffer,0,sizeof(echoBuffer));
if ((rcvMsgSize = recv(clntdataSocket, echoBuffer,
RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");

if (strcmp(echoBuffer,"Unable to Locate File") == 0){


printf ("\n%s\n",echoBuffer);
}
else{
strcpy(ip_addr,echoBuffer);

if ((rcvMsgSize = recv(clntdataSocket, echoBuffer,


RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");
echoBuffer[rcvMsgSize]='\0';
port_number = atoi(echoBuffer);

printf("\n\nThe File Searched is in:\n IP Address:


%s \n Port #: %d\n\n",ip_addr,port_number);
}
}
else if (strcmp(command,"DISCOVER") == 0)
{
memset(&echoBuffer,0,sizeof(echoBuffer));
printf("\nPlease enter <depth>\n");
gets(echoBuffer);

strcpy(depth,echoBuffer);
echoStringLen = strlen(echoBuffer);

if (send(sock,echoBuffer,echoStringLen,0) != echoStringLen)
DieWithError("send() failed");

memset(&echoBuffer,0,sizeof(echoBuffer));
if ((rcvMsgSize = recv(clntdataSocket, echoBuffer,
RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");
strcpy(ip_addr,echoBuffer);

printf("\n\nThe Active hosts are:\n IP Address: Port #: \n


%s \n",ip_addr,port_number);

}
else if (strcmp(command,"GET") == 0)
{
memset(&echoBuffer,0,sizeof(echoBuffer));
printf("\n<filname>\n");
gets(echoBuffer);
strcpy(fileName1,echoBuffer);

memset(&echoBuffer,0,sizeof(echoBuffer));
printf("\n<ip_address>\n");
gets(echoBuffer);
strcpy(ip_addr,echoBuffer);

memset(&echoBuffer,0,sizeof(echoBuffer));
printf("\n<port_number>\n");
gets(echoBuffer);
port_number = atoi(echoBuffer);

/* Create a reliable, stream socket using TCP */


if ((sock1 = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

/* Construct the server address structure */


memset(&echoServAddr1, 0, sizeof(echoServAddr1)); /*
Zero out structure */
echoServAddr1.sin_family = AF_INET; /*
Internet address family */
echoServAddr1.sin_addr.s_addr = inet_addr(ip_addr); /*
Server IP address */
echoServAddr1.sin_port = htons(port_number); /*
Server port */
/* Establish the connection to the echo server */
if (connect(sock1, (struct sockaddr *) &echoServAddr1,
sizeof(echoServAddr1)) < 0)
DieWithError("connect() failed sdf");

totalBytesRcvd = 0;

srand(time(NULL));
sprintf(echoBuffer,"%d",rand()%9999);
echoStringLen = strlen(echoBuffer); /* Determine
input length */
portNumber = atoi(echoBuffer);
portNumberLength = sizeof(portNumber);

/* Send the string, including the null terminator, to the


server */
if (send(sock1, echoBuffer, echoStringLen, 0) !=
echoStringLen)
DieWithError("send() failed");

if ((rcvMsgSize = recv(sock1, echoBuffer, RCVBUFSIZE - 1,


0)) <= 0)
DieWithError("recv() failed or connection closed
prematurely");

echoBuffer[rcvMsgSize] = '\0';
instructionSize = atoi(echoBuffer);

if ((rcvMsgSize = recv(sock1, echoBuffer, instructionSize,


0)) <= 0)
DieWithError("recv() failed or connection closed
prematurely");

echoBuffer[rcvMsgSize] = '\0';
strcpy(instructions,echoBuffer);

if ((clntdataSocket1 = socket(PF_INET, SOCK_STREAM,


IPPROTO_TCP)) < 0)
DieWithError("socket() failed");

memset(&dataEchoServAddr1, 0, sizeof(dataEchoServAddr1));
/* Zero out structure */
dataEchoServAddr1.sin_family = AF_INET; /*
Internet address family */
dataEchoServAddr1.sin_addr.s_addr = inet_addr(ip_addr);
/* Server IP address */
dataEchoServAddr1.sin_port = htons(portNumber); /*
Server port */

if (connect(clntdataSocket1, (struct sockaddr *)


&dataEchoServAddr1, sizeof(dataEchoServAddr1)) < 0)
DieWithError("connect() client failed");

memset(&command, 0, sizeof(command));
strcpy(command,"GET");
echoStringLen = strlen(command);

if (send(sock1, command, echoStringLen, 0) != echoStringLen)


DieWithError("send() failed");

Sleep(200);
echoStringLen = strlen(fileName1);

if (send(sock1,fileName1,echoStringLen,0) != echoStringLen)
DieWithError("send() failed");

memset(&echoBuffer,0,sizeof(echoBuffer));
if ((rcvMsgSize = recv(clntdataSocket1, echoBuffer,
RCVBUFSIZE,0)) <= 0)
DieWithError("recv() failed");

echoBuffer[rcvMsgSize]='\0';
transSize = atoi(echoBuffer);

if (transSize != 0)
{
memset(&listFile,0,sizeof(listFile));
strcat(listFile,rootDirectory);
strcat(listFile,"\\");
strcat(listFile,fileName1);

if ((dfp = fopen(listFile, "wb")) == NULL)


printf("File cannot be created");

totBytesReceived = 0;

if (send(sock1,"PATHSET",sizeof(char)*7,0) !=
sizeof(char)*7)
DieWithError("send() failed");

while (totBytesReceived < transSize)


{
if((bytesReceived = recv(clntdataSocket1,
echoBuffer, RCVBUFSIZE, 0)) <= 0)
DieWithError("recv() failed");

fwrite(echoBuffer, sizeof(char),
bytesReceived, dfp);
totBytesReceived += bytesReceived;
}
fclose(dfp);
}
else
printf("File requested does not exist.
Restart\n\n");
memset(&listFile,0,sizeof(listFile));
strcat(listFile,rootDirectory);
strcat(listFile,"\\");
strcat(listFile,"List.txt");

if ((dfp = fopen(listFile, "a+")) == NULL)


printf("File cannot be opened");
else{
fprintf(dfp,"\n%s",fileName1);
fclose(dfp);
}

}
else
printf("Invalid command please try again\n\n");

printf("\n\n%s", instructions);
printf("\nEnter your next command...\n");
gets(echoBuffer);
strcpy(command,echoBuffer);
echoStringLen = strlen(command);

if (send(sock,command,echoStringLen,0) != echoStringLen)
DieWithError("send() failed");
}
printf("You have exited\n");

closesocket(sock);
WSACleanup();

getchar();
return(0);
}

int getSize2(char *file)


{
FILE *fp;
long fileSize=0;

if ((fp = fopen(file,"rb")) == NULL)


printf("Cannot open the File %s\n",file);
else
{
fseek(fp , 0, SEEK_END);
fileSize = ftell(fp);
rewind(fp);
fclose(fp);
}
return(fileSize);
}

void *ThreadMain2(void *threadArgs)


{
int clntSock; /* Socket descriptor for client connection */
char directory[100];
int portNumber;
int flag=0;
/* Guarantees that thread resources are deallocated upon return */

/* Extract socket file descriptor from argument */


clntSock = ((struct ThreadArgs *) threadArgs) -> clntSock;
strcpy(directory,((struct ThreadArgs *) threadArgs) -> directory);
flag = ((struct ThreadArgs *) threadArgs) ->flag;
portNumber = ((struct ThreadArgs *) threadArgs) ->portnumber;
//printf("calling server: %d %s",portNumber,((struct ThreadArgs *) threadArgs)
->directory);
server(portNumber,((struct ThreadArgs *) threadArgs) ->directory,((struct
ThreadArgs *)threadArgs)->knownPort,((struct ThreadArgs *)threadArgs)->knownIP);
((struct ThreadArgs *) threadArgs) -> flag = flag;
free(threadArgs); /* Deallocate memory for argument */
return (NULL);
}

TCP Echo Server:

#include "TCPEchoServerWS.h" /* TCP echo server includes */


#include <winsock2.h>

void *ThreadMain(void *arg); /* Main program of a thread */

/* Structure of arguments to pass to client thread */


struct ThreadArgs
{
int clntSock; /* Socket descriptor for client */
int localPort;
char directory[1000];
int knownPort;
char knownIP[100];
int flag;
int portnumber;
};

void server(int echoServPort, char fileDirectory[1000],int knownPort, char knownIP[100])


{
int servSock; /* Socket descriptor for server */
int clntSock; /* Socket descriptor for client */
/* Server port */
DWORD threadID; /* Thread ID from CreateThread() */
struct ThreadArgs *threadArgs; /* Pointer to argument structure for thread */
WSADATA wsaData; /* Structure for WinSock setup communication */
int flag=0;

if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) /* Load Winsock 2.0 DLL */


{
fprintf(stderr, "WSAStartup() failed");
exit(1);
}

servSock = CreateTCPServerSocket(echoServPort);

for (;;) /* Run forever */


{
clntSock = AcceptTCPConnection(servSock);
/* Create separate memory for client argument */
threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs));
threadArgs -> clntSock = clntSock;
threadArgs ->localPort = echoServPort;
threadArgs ->knownPort = knownPort;
strcpy(threadArgs->knownIP, knownIP);
threadArgs->flag = 0;
strcpy(threadArgs -> directory, fileDirectory);

if (CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadMain, threadArgs,


0, (LPDWORD) &threadID) == NULL)
DieWithError("pthread_create() failed");
if(threadArgs->flag)
{
break;
}
}
}

void *ThreadMain(void *threadArgs)


{
int clntSock; /* Socket descriptor for client connection */
char directory[100];
int portNumber;
int flag=0;
/* Guarantees that thread resources are deallocated upon return */

/* Extract socket file descriptor from argument */


clntSock = ((struct ThreadArgs *) threadArgs) -> clntSock;
strcpy(directory,((struct ThreadArgs *) threadArgs) -> directory);
flag = ((struct ThreadArgs *) threadArgs) ->flag;
HandleTCPClient(clntSock,((struct ThreadArgs *) threadArgs)
->localPort,directory,&flag,((struct ThreadArgs *) threadArgs) -> knownPort,((struct
ThreadArgs *) threadArgs) -> knownIP);
free(threadArgs); /* Deallocate memory for argument */
((struct ThreadArgs *) threadArgs) -> flag = flag;
return (NULL);
}

Experimental Results:
LIST COMMAND used for Peer operating on Socket 6010

LISTR Command Listing Files under Peer 6010 using Peer 6020

SEARCH command used to search for file Pic1.jpg


LIST used
DISCOVER using 3 ACTIVE PEERS

USING GET command to download a file from a peer.


Issues Encountered:
Initially, we had trouble getting LISTR to work but eventually we debugged the
code and got that to work. We also had a minor issue where our QUIT part was
not working properly and the Server was shutting down improperly. This was
taken care of as well.

TA:
We Demoed with TA Zhongliang on Friday, 8th April 2010.

Conclusion:
This lab was a good practice of creating a peer-to-peer file-sharing program. We
were amazed as to how quickly big video files were getting transferred to other
students’ computers. As lots of time was spent on coding and debugging the
program, I guess we won’t be taking the common file sharing programs we use
every day for granted. Actually, we decided that we would improve the code even
further and use the program created by us to transfer files among ourselves from
now on instead of transferring files via msn and other programs.