Code:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <time.h>
#include <semaphore.h>
#include <fcntl.h>
#define PORT 6789 // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
#define BUFFER_SIZE 1024
int user, permPacketSize, timeoutType, timeoutInterval, sitErr;
sem_t sem_transfer;
/***********************************************************************************/
/*************************** ******************************/
/*************************** SERVER ******************************/
/*************************** ******************************/
/***********************************************************************************/
int runServer()
{
int sock, msgsock, sin_size; // listen on sock, new connection on msgsock
struct sockaddr_in server; // socket struct for server connection
struct sockaddr_in client; // socket struct for client connection
char fromClient[BUFFER_SIZE]; // String from client
char toClient[BUFFER_SIZE]; // String sent to client
int temp; // temp int for calculations
int packetSize;
unsigned int seqNum = 0;
sem_init(&sem_transfer, 0, 1); // initialize semaphore to 1
int fdServer;
int bytes_read, bytes_written;
/* Open a socket */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/* Fill out server sockaddr_in struct */
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
/* Bind */
if (bind(sock, (struct sockaddr *) &server, sizeof(server)) == -1) {
perror("bind");
exit(2);
}
/* Listen w/ max queue of defined BACKLOG value */
if (listen(sock, BACKLOG) == -1) {
perror("listen");
exit(3);
}
sin_size = sizeof(struct sockaddr_in);
if ((msgsock = accept(sock, (struct sockaddr *)&client, &sin_size)) == -1) {
perror("accept");
}
// get file to copy
char filename_received[BUFFER_SIZE];
if (recv(msgsock, filename_received, BUFFER_SIZE,0) < 0){
perror("Aborting");
close(msgsock);
exit(4);
}
fprintf(stderr, "file to be copied: %s\n",filename_received);
char *copy;
copy = (char*) malloc (sizeof(char)*1024);
strcpy(copy, filename_received);
if ( (fdServer = open (copy, O_RDONLY)) == -1) {
perror ( "Error in opening the input file:");
exit (1);
}
free(copy);
// Determine lowest packet size between client and server
sprintf(toClient, "%d", permPacketSize);
send(msgsock, toClient, sizeof(toClient),0);
if (recv(msgsock, fromClient, BUFFER_SIZE,0) < 0){
perror("Aborting");
close(msgsock);
exit(4);
}
temp = atoi(fromClient);
if (temp < permPacketSize){
packetSize = temp;
}
else {
packetSize = permPacketSize;
}
fprintf(stderr, "The agreed upon packet size is %d\n", packetSize);
while (1)
{
void* buffer = (void*) malloc (packetSize);
bytes_read = read(fdServer, buffer, packetSize);
if (bytes_read == 0){
break;
}
void *p = buffer;
while (bytes_read > 0){
bytes_written = write(msgsock, p, bytes_read);
bytes_read -= bytes_written;
p += bytes_written;
}
free(buffer);
fprintf(stderr, "sending %d\n", seqNum);
seqNum++;
}
sprintf(toClient, "FINISHED\n");
send(msgsock, toClient, sizeof(toClient),0);
// close all open fd's and sockets
close(msgsock);
close(sock);
close(fdServer);
}
/***********************************************************************************/
/*************************** ******************************/
/*************************** CLIENT ******************************/
/*************************** ******************************/
/***********************************************************************************/
int runClient()
{
int sock; // fd for socket connection
struct sockaddr_in server; // Socket info. for server
struct hostent *host; // Server info
char selection[BUFFER_SIZE]; // User's input
char toServer[BUFFER_SIZE]; // String sent to server
char fromServer[BUFFER_SIZE]; // String rec'd from server
int temp; // temp int for calculations
int packetSize;
unsigned int ackNum = 0;
char* userInput;
userInput = (char*) malloc (sizeof(toServer));
int fdClient;
int bytes_read, bytes_written;
// get server address
fprintf(stderr, "Enter the address of the server.\n");
scanf("%s", userInput);
// Fill out sockaddr struct
server.sin_family = AF_INET;
if ((host = gethostbyname(userInput)) == NULL){
printf("Unknown host.\n");
exit(1);
}
server.sin_family = host->h_addrtype;
memcpy((char *) &server.sin_addr.s_addr, host->h_addr_list[0], host->h_length);
server.sin_port = htons((u_short) PORT);
// Create socket
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("Unable to open socket\n");
perror("Aborting");
exit(1);
}
// Try to connect
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0){
printf("Unable to connect to %s\n", userInput);
perror("Aborting");
exit(1);
}
// request file to copy
printf("Enter a file name:\n");
scanf("%s",userInput);
fprintf(stderr, "You entered: %s\n",userInput);
char filename_buf[BUFFER_SIZE];
strcpy(filename_buf, userInput);
if (send(sock, filename_buf, sizeof(filename_buf),0) <0)
{
perror("Aborting");
close(sock);
exit(42);
}
if ( (fdClient = open (userInput, (O_WRONLY | O_CREAT), 0740)) == -1 )
{
perror ( "Error in creating the output file:");
exit (11);
}
free(userInput);
// Determine lowest packet size between client and server
sprintf(toServer, "%d", permPacketSize);
send(sock, toServer, sizeof(toServer),0);
if (recv(sock, fromServer, BUFFER_SIZE,0) < 0)
{
perror("Aborting");
close(sock);
exit(4);
}
temp = atoi(fromServer);
if (temp < permPacketSize){
packetSize = temp;
}
else {
packetSize = permPacketSize;
}
fprintf(stderr, "The agreed upon packet size is %d\n", packetSize);
while(1)
{
void* buffer = (void*) malloc (packetSize);
bytes_read = read(sock, buffer, packetSize);
if (bytes_read == 0){
break;
}
void *p = buffer;
while (bytes_read > 0){
bytes_written = write(fdClient, p, bytes_read);
bytes_read -= bytes_written;
p += bytes_written;
}
free(buffer);
fprintf(stderr, "receiving %d\n", ackNum);
ackNum++;
}
close(sock);
printf("All done. Connection to server terminated. Exiting...\n");
}
/***********************************************************************************/
/*************************** ******************************/
/*************************** MAIN ******************************/
/*************************** ******************************/
/***********************************************************************************/
int main(int argc, char *argv[])
{
// determine client or server
fprintf(stderr, "\nWelcome to the Reliable Transmission Project.\n");
fprintf(stderr, "Please make the following numerical selections.\n\n");
fprintf(stderr, "0) Server\n");
fprintf(stderr, "1) Client\n");
scanf("%d", &user);
if (user == 0){
fprintf(stderr, "You have chosen to be the server.\n");
}
else{
fprintf(stderr, "You have chosen to be the client.\n");
}
// determine packet size
fprintf(stderr, "\nPlease enter the packet size you would like to use (in bytes).\n");
scanf("%d", &permPacketSize);
fprintf(stderr, "You have chosen a packet size of %d bytes.\n", permPacketSize);
// determine how to calculate timeout interval
fprintf(stderr, "\nWould you like the timeout interval to be determined manually or dynamically?\n\n");
fprintf(stderr, "0) Set timeout interval manually\n");
fprintf(stderr, "1) Automatic time interval\n");
scanf("%d", &timeoutType);
if (timeoutType == 0){
fprintf(stderr, "What would you like the timeout interval to be (in milliseconds)?\n");
scanf("%d", &timeoutInterval);
fprintf(stderr, "You have chosen a timeout interval of %d milliseconds.\n", timeoutInterval);
}
else{
fprintf(stderr, "The timeout interval will be automatically ping-calculated.\n");
timeoutInterval = 4213;
}
/*****************************************************************
******************************************************************
// determine situational errors
fprintf(stderr, "\nDo you want to introduce situational errors?\n\n");
fprintf(stderr, "0) No\n");
fprintf(stderr, "1) Yes\n");
scanf("%d", &sitErr);
if (sitErr == 0){
fprintf(stderr, "No situational errors will be used.\n");
}
else{
fprintf(stderr, "Which situational error would you like to introduce?\n");
fprintf(stderr, "1) Drop packets\n");
fprintf(stderr, "2) Lose ACKs\n");
fprintf(stderr, "3) Send damaged packets\n");
fprintf(stderr, "4) Random\n");
scanf("%d", &sitErr);
if(sitErr == 1){
fprintf(stderr, "You have chosen to have some packets get dropped.\n");
}
else if(sitErr == 2){
fprintf(stderr, "You have chosen to lose some ACK commands.\n");
}
else if(sitErr == 3){
fprintf(stderr, "You have chosen to send some damaged packets.\n");
}
else{
fprintf(stderr, "You have chosen to have a random error selected.\n");
srand((unsigned)time(NULL));
sitErr = (rand() % 3 + 1);
if(sitErr==1)
fprintf(stderr, "You will have some packets get dropped.\n");
else if(sitErr==2)
fprintf(stderr, "You will lose some ACK commands.\n");
else
fprintf(stderr, "You will send some damaged packets.\n");
}
}
**********************************************
********************************************/
// all settings are entered, run client/server
if(user){
runClient();
}
else{
runServer();
}
return 0;
}