diff --git a/main.cpp b/main.cpp index 4f825bf..830b3fe 100644 --- a/main.cpp +++ b/main.cpp @@ -25,6 +25,8 @@ using namespace std; const int PORT_NUM = 8888; const string IP_ADDRESS = "127.0.0.1"; +const int DEFAULT_CUR_X = 2;//the x position of the preferred default cursor position for message entry +const int DEFAULT_CUR_Y = 12;//the x position of the preferred default cursor position for message entry int mode = 0; //what mode is this program in. 0 = nothing. 1 = server. 2 = client int serverSocketDescriptor;//a global variable for storing the server socket descriptor. @@ -40,11 +42,14 @@ int bytesRead, bytesWritten = 0; const int LOG_LENGTH = 10;//number of text log file lines to display int linePos = 0; //counter for what current position to use in the file +string logFileName;//the name of the log file + pthread_t client_wait_thread; int writeToFile(string path, string line, bool incLineNum = true); void* waitForClient(void* argss); void* pollForClient(); +void* pollForSever(void* args); //clears ncurses rows in a specific region only void clearRows(int startingRow, int endingRow) @@ -89,6 +94,8 @@ int displayFile(string path, int startLineNum = 0, int numLines = 10) } num++; } + move(DEFAULT_CUR_Y, DEFAULT_CUR_X); + refresh(); return 0; } } @@ -119,6 +126,7 @@ struct waitClientArgs { sockaddr_in newSockAddr; socklen_t newSockAddrSize; + int auxInt;//used in client mode because I didn't want to make another struct to keep track of }; void* waitForClient(void* argss) @@ -127,8 +135,12 @@ void* waitForClient(void* argss) clientSocketDescriptor = accept(serverSocketDescriptor, (sockaddr *)&args->newSockAddr, &args->newSockAddrSize); if (clientSocketDescriptor >= 0) { - writeToFile("test.txt", "client connected"); - displayFile("test.txt", linePos, LOG_LENGTH); + writeToFile(logFileName, "client connected"); + if (linesInFile(logFileName) > LOG_LENGTH) + { + linePos++; + } + displayFile(logFileName, linePos, LOG_LENGTH); } delete args;//delete to avoid memory leaks @@ -143,8 +155,12 @@ void* pollForClient() //receive a message from the client (listen) memset(&msg, 0, sizeof(msg));//clear the buffer bytesRead += recv(clientSocketDescriptor, (char*)&msg, sizeof(msg), 0); - writeToFile("test.txt", msg);//write the client's message to file - displayFile("test.txt", linePos, LOG_LENGTH); + writeToFile(logFileName, msg);//write the client's message to file + if (linesInFile(logFileName) > LOG_LENGTH) + { + linePos++; + } + displayFile(logFileName, linePos, LOG_LENGTH); } return nullptr; @@ -165,6 +181,9 @@ int setupServer(int port) serverSocketDescriptor = socket(AF_INET, SOCK_STREAM, 0); if(serverSocketDescriptor < 0) { + //keeps from bricking the terminal if this happens + endwin(); + cerr << "Error establishing the server socket" << endl; exit(0); } @@ -173,10 +192,13 @@ int setupServer(int port) sizeof(servAddr)); if(bindStatus < 0) { + //keeps from bricking the terminal if this happens + endwin(); + cerr << "Error binding socket to local address" << endl; exit(0); } - writeToFile("test.txt", "Waiting for a client to connect..."); + writeToFile(logFileName, "Waiting for a client to connect..."); //listen for up to 5 requests at a time listen(serverSocketDescriptor, 5); //receive a request from client using accept @@ -190,7 +212,7 @@ int setupServer(int port) aaa->newSockAddrSize = newSockAddrSize; int rc = pthread_create(&client_wait_thread, nullptr, waitForClient, aaa); pthread_detach(client_wait_thread); - writeToFile("test.txt", "Server started sucessfully"); + writeToFile(logFileName, "Server started sucessfully"); gettimeofday(&start1, NULL); /*while(1) @@ -248,6 +270,45 @@ void closeClient() cout << "Connection closed" << endl; } +void* pollForSever(void* args) +{ + waitClientArgs* aaa = static_cast(args); + int socketDescriptor = (int)aaa->auxInt; + char msg[1024]; + while(1) + { + /*string data; + getline(cin, data); + memset(&msg, 0, sizeof(msg));//clear the buffer + strcpy(msg, data.c_str()); + if(data == "exit") + { + send(*socketDescriptor, (char*)&msg, strlen(msg), 0); + break; + }*/ + //bytesWritten += send(*socketDescriptor, (char*)&msg, strlen(msg), 0); + //writeToFile(logFileName, msg); + //displayFile(logFileName, linePos, LOG_LENGTH); + memset(&msg, 0, sizeof(msg));//clear the buffer + bytesRead += recv(socketDescriptor, (char*)&msg, sizeof(msg), 0); + + //not needed for proofs of concept testing + /*if(!strcmp(msg, "exit")) + { + writeToFile(logFileName, msg); + displayFile(logFileName, linePos, LOG_LENGTH); + break; + }*/ + //cout << "Server: " << msg << endl; + writeToFile(logFileName, msg); + if (linesInFile(logFileName) > LOG_LENGTH) + { + linePos++; + } + displayFile(logFileName, linePos, LOG_LENGTH); + } +} + void setupClient() { //we need 2 things: ip address and port number, in that order @@ -271,12 +332,16 @@ void setupClient() (sockaddr*) &sendSockAddr, sizeof(sendSockAddr)); if(status < 0) { - writeToFile("test.txt", "Error connecting to socket!"); + writeToFile(logFileName, "Error connecting to socket!"); } - writeToFile("test.txt", "Connected to the server!"); + writeToFile(logFileName, "Connected to the server!"); int bytesRead, bytesWritten = 0; struct timeval start1, end1; gettimeofday(&start1, NULL); + auto* aaa = new waitClientArgs{};//it looks stupid but it works + aaa->auxInt = clientSocketDescriptor; + int rc = pthread_create(&client_wait_thread, nullptr, pollForSever, aaa); + pthread_detach(client_wait_thread); /*while(1)s { cout << ">"; @@ -331,43 +396,45 @@ int main(int argc, char *argv[]) if (argc > 1 && argv[1][0] == 'c') { //client mode + logFileName = "client.txt"; mode = 2; } else { //server mode + logFileName = "server.txt"; mode = 1; } - + //putting this lower down to circumvent the terminal brick when the socket was already in use results in all network functonality no longer working. initscr();//creates stdscr. important step use_default_colors();//this apparently tells it to use default terminal colors whenever there is no color attribute applied //printw("Starting server..."); //you have to do this to make the scrolling still work correctly if there was already content in the log file - linePos = linesInFile("test.txt") - LOG_LENGTH + 1; + linePos = linesInFile(logFileName) - LOG_LENGTH + 1; char *userInput = new char[1024]; bool exit = false; if (mode == 2) { - writeToFile("test.txt", "CLIENT MODE"); + writeToFile(logFileName, "CLIENT MODE"); setupClient(); } else if (mode == 1) { - writeToFile("test.txt", "SERVER MODE"); + writeToFile(logFileName, "SERVER MODE"); setupServer(PORT_NUM); } while (!exit) { - displayFile("test.txt", linePos, LOG_LENGTH); + displayFile(logFileName, linePos, LOG_LENGTH); //scroll along the screen if and when required so that it stays in sync - if (linesInFile("test.txt") > LOG_LENGTH) + if (linesInFile(logFileName) > LOG_LENGTH) { linePos++; } @@ -375,14 +442,14 @@ int main(int argc, char *argv[]) move(12, 0); printw("> "); getstr(userInput); - writeToFile("test.txt", userInput); + writeToFile(logFileName, userInput); if (mode == 1) { - send(clientSocketDescriptor, (char*)&userInput, strlen(userInput), 0); + send(clientSocketDescriptor, (char*)userInput, strlen(userInput), 0); } else { - send(clientSocketDescriptor, (char*)&userInput, strlen(userInput), 0); + send(clientSocketDescriptor, (char*)userInput, strlen(userInput), 0); } } @@ -390,100 +457,4 @@ int main(int argc, char *argv[]) closeServer(); return 0; -} - -//Server side -int main_old(int argc, char *argv[]) -{ - //for the server, we only need to specify a port number - if(argc != 2) - { - cerr << "Usage: port" << endl; - exit(0); - } - //grab the port number - int port = atoi(argv[1]); - //buffer to send and receive messages with - char msg[1500]; - - //setup a socket and connection tools - sockaddr_in servAddr; - bzero((char*)&servAddr, sizeof(servAddr)); - servAddr.sin_family = AF_INET; - servAddr.sin_addr.s_addr = htonl(INADDR_ANY); - servAddr.sin_port = htons(port); - - //open stream oriented socket with internet address - //also keep track of the socket descriptor - int serverSd = socket(AF_INET, SOCK_STREAM, 0); - if(serverSd < 0) - { - cerr << "Error establishing the server socket" << endl; - exit(0); - } - //bind the socket to its local address - int bindStatus = bind(serverSd, (struct sockaddr*) &servAddr, - sizeof(servAddr)); - if(bindStatus < 0) - { - cerr << "Error binding socket to local address" << endl; - exit(0); - } - cout << "Waiting for a client to connect..." << endl; - //listen for up to 5 requests at a time - listen(serverSd, 5); - //receive a request from client using accept - //we need a new address to connect with the client - sockaddr_in newSockAddr; - socklen_t newSockAddrSize = sizeof(newSockAddr); - //accept, create a new socket descriptor to - //handle the new connection with client - int newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize); - if(newSd < 0) - { - cerr << "Error accepting request from client!" << endl; - exit(1); - } - cout << "Connected with client!" << endl; - //lets keep track of the session time - struct timeval start1, end1; - gettimeofday(&start1, NULL); - //also keep track of the amount of data sent as well - int bytesRead, bytesWritten = 0; - while(1) - { - //receive a message from the client (listen) - cout << "Awaiting client response..." << endl; - memset(&msg, 0, sizeof(msg));//clear the buffer - bytesRead += recv(newSd, (char*)&msg, sizeof(msg), 0); - if(!strcmp(msg, "exit")) - { - cout << "Client has quit the session" << endl; - break; - } - cout << "Client: " << msg << endl; - cout << ">"; - string data; - getline(cin, data); - memset(&msg, 0, sizeof(msg)); //clear the buffer - strcpy(msg, data.c_str()); - if(data == "exit") - { - //send to the client that server has closed the connection - send(newSd, (char*)&msg, strlen(msg), 0); - break; - } - //send the message to client - bytesWritten += send(newSd, (char*)&msg, strlen(msg), 0); - } - //we need to close the socket descriptors after we're all done - gettimeofday(&end1, NULL); - close(newSd); - close(serverSd); - cout << "********Session********" << endl; - cout << "Bytes written: " << bytesWritten << " Bytes read: " << bytesRead << endl; - cout << "Elapsed time: " << (end1.tv_sec - start1.tv_sec) - << " secs" << endl; - cout << "Connection closed..." << endl; - return 0; } \ No newline at end of file