I don't really know what is wrong with this program. It's a simple client and server that sends a small file using udp. I know the code is a little sloppy, but all I want
to do for now is make it work, then I can modularize it later. I would really appreciate it if someone could sift through this code, and maybe explain to me the reasons it
won't work. As far as I can tell at the moment, it's a problem with the ports not being set properly, and there appears to be some memory problems too, because when
I take out some variable declarations, the program crashes sooner(?????????). Thanks for your help!
server:
#include <iostream>
#include <string>
#include <strings.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include "server.hh"
using namespace std;
int main(int argc, char** argv) {
//some variables needed
#define BUFFER_LENGTH 1024
#define MAX_MSG_LEN 10
#define PORT_CMD_SUCC "200"
#define GOOD_BYE "221"
#define TRANSFER_DONE "001"
#define TRANSFER_NOTDONE "000"
#define CNTRL_PORT 2021
#define DATA_PORT 2020
int welcomeSocket, dataSocket;
struct sockaddr_in serverAddress;
struct sockaddr *host_cntrl;
struct sockaddr *host_data;
struct hostent *hp;
int rval, length;
char* message[MAX_MSG_LEN];
char ftp_buffer[BUFFER_LENGTH];
FILE * ftpfile;
//open the welcome socket
cout << "Creating welcome socket..." << endl;
welcomeSocket = create_socket(AF_INET, SOCK_DGRAM, 0, CNTRL_PORT, INADDR_ANY, &serverAddress);
if(welcomeSocket < 0) {
perror("Error creating server socket");
exit(1);
}
cout << "Binding the welcome socket..." << endl;
if(bind(welcomeSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) {
perror("Error binding server socket");
exit(1);
}
//infinite loop
do{
cout << "Server ready and waiting..." << endl;
//get message from client
//bzero(message, sizeof(message));
cout << "Receiving message..." << endl;
if((rval = (receive_message(welcomeSo
cket, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, message, MAX_MSG_LEN))) < 0)
perror("Error reading stream message");
else if(rval == 0)
cout << "No message....terminating" << endl << endl;
else {
//Check message to determine command
//If the message is get
if(strcmp(message[0],"get"
) == 0) {
cout << "Get message received..." << endl;
if(rval < 2) {
cout << "No filename specified...unable to continue transfer..." << endl;
}
else {
char* filename = message[1];
cout << "Filename specified: " << filename << endl;
if((ftpfile = fopen(filename, "r")) == NULL) {
cout << "Error opening file " << filename << "." << endl << endl;
}
else {
cout << "Sending response " << PORT_CMD_SUCC << "..." << endl;
if((send_message(PORT_CMD_
SUCC, welcomeSocket, strlen(PORT_CMD_SUCC), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending response PORT_CMD_SUCC");
}
int control_port = serverAddress.sin_port;
//Create the data transfer socket
cout << "Opening data transfer socket..." << endl;
dataSocket = create_socket(AF_INET, SOCK_DGRAM, 0, DATA_PORT, INADDR_ANY, &serverAddress);
if(dataSocket < 0) {
perror("Error creating data socket");
exit(1);
}
//Bind the socket to port 2020
cout << "Binding data transfer socket to port " << DATA_PORT << "..." << endl;
if(bind(dataSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) {
perror("Error binding data socket");
exit(1);
}
bzero(message, sizeof(message));
cout << "Waiting for info from client..." << endl;
if((rval = (receive_message(dataSocke
t, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, message, MAX_MSG_LEN))) < 0)
perror("Error reading stream message");
else if(rval == 0)
cout << "No message....ending connection...." << endl << endl;
int message_port = serverAddress.sin_port;
cout << "Sending file..." << endl << endl;
while(!feof(ftpfile)) {
serverAddress.sin_port = control_port;
if((send_message(TRANSFER_
NOTDONE, welcomeSocket, strlen(TRANSFER_NOTDONE), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending TRANSFER_NOTDONE response");
}
cout << ".";
fread(ftp_buffer, 1, 1024, ftpfile);
serverAddress.sin_port = message_port;
if((send_message(ftp_buffe
r, dataSocket, strlen(ftp_buffer), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending file");
close(dataSocket);
}
}
serverAddress.sin_port = control_port;
if((send_message(TRANSFER_
DONE, welcomeSocket, sizeof(TRANSFER_DONE), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending TRANSFER_DONE response");
}
cout << "Transfer complete...closing data transfer socket..." << endl << endl;
close(dataSocket);
}//else file opened
}//else filename is specified
}//if get command received
//If the message was bye
else if(strcmp(message[0],"bye"
) == 0) {
cout << "Bye command received..." << endl;
cout << "Sending response " << GOOD_BYE << endl;
//Send response
if((send_message(GOOD_BYE,
welcomeSocket, strlen(GOOD_BYE), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending response code GOOD_BYE");
}
//Close the sockets and terminate the program
cout << "Closing sockets and terminating..." << endl;
close(welcomeSocket);
close(dataSocket);
return 0;
}
//Otherwise the message was not understood.
else{
cout << "Message not understood...closing connection..." << endl << endl;
fflush(stdout);
rval = 0;
}
}
}while(1);
close(welcomeSocket);
return 0;
}//main
int create_socket(int domain, int type, int protocol, in_port_t port, in_addr_t address, struct sockaddr_in *host) {
int new_socket;
new_socket = socket(domain, type, protocol);
host->sin_family = domain;
host->sin_addr.s_addr = address;
host->sin_port = htons(port);
return new_socket;
}
int send_message(char* message, int socket, size_t length, int flags, const struct sockaddr *to, socklen_t tolen) {
int rval;
rval = sendto(socket, message, length, flags, to, tolen);
return rval;
}
int receive_message(int socket, size_t length, int flags, struct sockaddr *from, char** message, size_t msg_len) {
char *next = NULL;
int rval;
size_t i = 0;
socklen_t *fromlen;
void *buffer;
buffer = malloc(length*sizeof(char)
);
if((rval = recvfrom(socket, buffer, length, flags, from, &fromlen)) <= 0) {
free(buffer);
return rval;
}
rval = 0;
next = strtok((char*)buffer, " ");
do{
rval++;
message[i] = next;
next = strtok(NULL, " ");
i++;
}while(next != NULL && i < msg_len);
free(buffer);
return rval;
}
and the client:
#include <iostream>
#include <strings.h>
#include <string>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
int create_socket(int domain, int type, int protocol, in_port_t port, in_addr_t address, struct sockaddr_in *host) {
int new_socket;
new_socket = socket(domain, type, protocol);
host->sin_family = domain;
host->sin_addr.s_addr = address;
host->sin_port = htons(port);
return new_socket;
}
int send_message(const char* message, int socket, size_t length, int flags, const struct sockaddr *to, socklen_t tolen) {
int rval;
rval = sendto(socket, message, length, flags, to, tolen);
return rval;
}
int process_command(string &command, int length) {
cout << "Commands:" << endl << "--get <filename>-- will get <filename> from host and copy to current directory. " << endl << "--bye -- will close the connection and terminate the server and this program. " << endl << endl << ">>>>";
string line;
string filename;
int i = 1;
cin >> line;
command = line;
if(line == "get") {
cin >> filename;
command.append(" ");
command.append(filename);
i++;
}
return i;
}
int main(int argc, char** argv) {
//Setting up required variables.
#define PORT_CMD_SUCC "200"
#define GOOD_BYE "221"
#define BUFFER_LENGTH 1024
//#define MAX_MSG_LEN 10
#define TRANSFER_DONE "001"
#define TRANSFER_NOTDONE "000"
#define NUM_CMNDS 2
string GET("get");
string BYE("bye");
int messageSocket;
int controlSocket;
int rval, length;
struct sockaddr_in serverAddress;
struct sockaddr_in dataAddress;
struct hostent *hp;
string command;
string command_line;
char* message = (char*)malloc(sizeof(char)
*BUFFER_LE
NGTH);
string filename;
FILE* ftpfile;
//Checking command line for host name
if(argc < 2) {
cout << "Usage: client <hostname>, where <hostname> is the name of the server host." << endl << endl;
return 0;
}
//opening a control socket
if((controlSocket = create_socket(AF_INET, SOCK_DGRAM, 0, 0, INADDR_ANY, &serverAddress)) < 0) {
perror("Error opening control socket");
exit(1);
}
if(bind(controlSocket, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) {
perror("Error binding socket");
exit(1);
}
//Getting host by name, as specified on the command line
cout << "Checking for host..." << endl;
if((hp = gethostbyname(argv[1])) == NULL) {
cout << argv[1] << ": Unkown host." << endl << endl;
exit(2);
}
bcopy(hp->h_addr, &serverAddress.sin_addr, hp->h_length);
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(2021);
length = sizeof(serverAddress);
//Infinite loop, until command bye is entered.
while(1) {
int num_cmnds = process_command(command_li
ne, NUM_CMNDS);
fflush(stdout);
command = command_line.substr(0,3);
if(command == "get") {
if(num_cmnds < 2){
cout << "Invalid filename!" << endl;
}//if num-cmnds < 2
else {
filename = command_line.substr(4,comm
and_line.l
ength());
}//else num-cmnds = 2
cout << "Sending get " << filename << " command to server..." << endl;
if((send_message(command_l
ine.c_str(
), controlSocket, command_line.length(), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending file request");
}
bzero(message, sizeof(message));
cout << "Waiting for response..." << endl;
if((rval = (recvfrom(controlSocket, message, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, &length))) < 0) {
perror("Error reading stream message");
}
else if(rval == 0)
cout << "No response....terminating" << endl;
else {
if(strcmp(message, PORT_CMD_SUCC) == 0) {
cout << "Response received...preparing for transfer" << endl;
cout << "Creating data socket" << endl;
if((messageSocket = create_socket(AF_INET, SOCK_DGRAM, 0, 0, INADDR_ANY, &dataAddress)) < 0) {
perror("Error opening control socket");
exit(1);
}
if(bind(messageSocket, (struct sockaddr*)&dataAddress, sizeof(dataAddress))) {
perror("Error binding socket");
exit(1);
}
cout << "Sending info to server..." << endl;
serverAddress.sin_port = htons(2020);
if((send_message(" ", messageSocket, 1, 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending port to server");
}
else {
cout << "Opening file " << filename << "..." << endl;
if((ftpfile = fopen(filename.c_str(), "w")) == NULL) {
cout << "Error opening file " << filename << "." << endl;
}
else {
cout << "Receiving file..." << endl;
length = sizeof(serverAddress);
if((rval = (recvfrom(controlSocket, message, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, &length))) <= 0) {
perror("Error reading transfer status");
}
while(strcmp(message,TRANS
FER_NOTDON
E) == 0) {
cout << ".";
length = sizeof(serverAddress);
if((rval = (recvfrom(messageSocket, message, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, &length))) < 0) {
perror("Error reading file transfer stream");
close(messageSocket);
fclose(ftpfile);
break;
}
fwrite(message, 1, sizeof(message), ftpfile);
length = sizeof(serverAddress);
if((rval = (recvfrom(controlSocket, message, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, &length))) <= 0) {
perror("Error reading transfer status");
}
}//while transfer not done
cout << "File tranfer complete...closing file and socket" << endl;
close(messageSocket);
fclose(ftpfile);
}//else file opened
} //port num sent successfully
}//PORT_CMD_SUCC response received
else
cout << "Unexpected response code...terminating..." << endl;
}//else responsecode received.
}//command = get
//if the command is bye, terminate the program after receiving the
//response code.
else if(command == "bye") {
cout << "Bye command understood..." << endl;
cout << "Sending 'bye' command to server..." << endl;
if((send_message(command.c
_str(), controlSocket, command.length(), 0, (struct sockaddr*)&serverAddress, sizeof(serverAddress))) < 0) {
perror("Error sending bye command");
}
cout << "Waiting for response..." << endl;
length = sizeof(serverAddress);
bzero(message, sizeof(message));
if((rval = (recvfrom(controlSocket, message, BUFFER_LENGTH, 0, (struct sockaddr*)&serverAddress, &length))) <= 0) {
perror("Error reading response code");
exit(1);
}
cout << "Response received...checking..." << endl;
if(strcmp(message, GOOD_BYE) == 0) {
cout << "Correct response received, ending program..." << endl;
free(message);
close(controlSocket);
return 0;
}
else {
cout << "Unexpected response...server terminating abnormally" << endl;
cout << "Response: " << message << " is incorrect" << endl;
close(controlSocket);
free(message);
return 1;
}
}
//Otherwise, and incorrect command, and start loop over again
else {
cout << "Incorrect command!" << endl << endl;
}
}
free(message);
return 0;
}
I know it's really long, and tedious code, sorry! Please know, however, that I will REALLY REALLY appreciate any help. Thanks again!
__fletcher__