From 5e41e889611252d961d65517be6dbdca755270c9 Mon Sep 17 00:00:00 2001 From: "jazz (gitea)" Date: Thu, 12 Mar 2026 15:56:28 -0500 Subject: [PATCH] initial commit --- .clang-format | 20 +++++ Makefile | 18 +++++ README.md | 34 +++++++++ STYLE.md | 122 ++++++++++++++++++++++++++++++ client.cc | 90 ++++++++++++++++++++++ client.h | 8 ++ com.txt | 2 + disp.cc | 55 ++++++++++++++ disp.h | 11 +++ format-configs/.editorconfig | 32 ++++++++ format-configs/clang-format.json | 20 +++++ format-configs/clang-format.yml | 21 ++++++ log.cc | 44 +++++++++++ log.h | 9 +++ main.cc | 124 +++++++++++++++++++++++++++++++ public.h | 28 +++++++ server.cc | 123 ++++++++++++++++++++++++++++++ server.h | 9 +++ 18 files changed, 770 insertions(+) create mode 100644 .clang-format create mode 100644 Makefile create mode 100644 README.md create mode 100644 STYLE.md create mode 100644 client.cc create mode 100644 client.h create mode 100644 com.txt create mode 100644 disp.cc create mode 100644 disp.h create mode 100644 format-configs/.editorconfig create mode 100644 format-configs/clang-format.json create mode 100644 format-configs/clang-format.yml create mode 100644 log.cc create mode 100644 log.h create mode 100644 main.cc create mode 100644 public.h create mode 100644 server.cc create mode 100644 server.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..e2079be --- /dev/null +++ b/.clang-format @@ -0,0 +1,20 @@ +{ + "BasedOnStyle": "LLVM", + "UseTab": "Always", + "IndentWidth": 8, + "TabWidth": 8, + "ColumnLimit": 100, + "LineEnding": "LF", + "RemoveBracesLLVM": true, + "AlwaysBreakAfterReturnType": "AllDefinitions", + "BreakBeforeBraces": "Custom", + "BraceWrapping": { + "AfterFunction": true, + "AfterClass": false, + "AfterControlStatement": false, + "AfterNamespace": false, + "AfterStruct": false, + "BeforeElse": false, + "BeforeCatch": false + } +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..54c5d2a --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +# Compiler and flags +TARGET = ct +CXX = g++ +CXXFLAGS = -pthread -Wall -Wextra -O2 -std=c++17 -lcurses -g + +SRC = $(wildcard *.cc) +OBJ = $(SRC:.cc=.o) + +all: $(TARGET) + +clean: + rm -f $(TARGET) *.o + +$(TARGET): $(OBJ) + $(CXX) $(CXXFLAGS) $(OBJ) -o $(TARGET) + +%.o: %.cc + $(CXX) $(CXXFLAGS) -c $< -o $@ diff --git a/README.md b/README.md new file mode 100644 index 0000000..673baab --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# threaded network chat refactor + +https://www.youtube.com/watch?v=wecDU2t37gM + + + +## What now? + +See TODO. From here we're going to push the code to the gitlab like we were told to after everyone +is set up. Follow the coding style guidelines because otherwise everything will be extremely gross +and inconsistent. If you set up your editor correctly, it will take care of most of that stuff. + +## TODO + +- Finalize coding style, + - **see [STYLE.md](STYLE.md)** +- Get everyone's editors set up for clangd/clang-format and git +- Make sure everyone's compiler toolchains work +- Decide who gets what responsibilities +- Distribute appropriate code to people with those responsibilities +- Have everyone upload their respective code to their sections of the gitlab + +## Code + +Everything is in [src/](src). +A mostly untouched copy of [Scott's original code](https://git.therats.win/scott/threaded_network_chat) is also in [old/](old). +A reformatted version of that code is also in [modified-example.cc](modified-example.cc) but it can be ignored. + +## Build + +``` +cd src/ +make +``` diff --git a/STYLE.md b/STYLE.md new file mode 100644 index 0000000..8efbbcf --- /dev/null +++ b/STYLE.md @@ -0,0 +1,122 @@ +# Project Coding Style + +**Subject to change, let's please discuss this.** + +This is a less extreme version of the style I generally follow, and unless someone has a much better style I would +like to use this one for code we will be collaborating on. Feel free to ignore this if you plan for your own code to +be entirely your responsibility. + +Also don't swear on anything we expect to present to the professor. + +**Please install the [C/C++ Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools-extension-pack) and [clang-format](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format) for Visual Studio Code.** + +Follow the instructions in the previous link to set up the correctly. + +## TL;DR + +Call files `.cc` instead of `.c` or `.cpp` and use `.h` headers for everything. + +If you follow the setup instructions you should be fine. Otherwise: + +Use [BSD Kernel Normal Form (KNF)](https://en.wikipedia.org/wiki/Indentation_style#BSD_KNF) for function bodies +and [Kernighan & Ritchie (K&R)](https://en.wikipedia.org/wiki/Indentation_style#K&R) style (with a few modifications stated in **General Guidelines**) everywhere else. + +## Existing Literature + +I recommend skimming over these for inspiration. + +- [Names](https://research.swtch.com/names) - Russ Cox +- [Notes on Programming in C](http://doc.cat-v.org/bell_labs/pikestyle) - Rob Pike + +## General Guidelines + +- Use 8-width tabs, not spaces, for indentation. +- If you copy code from online, copy it by hand. +- Use [K&R style](https://en.wikipedia.org/wiki/Indentation_style#K&R) for indentation and brace placement where possible. + - When writing function bodies: + - return type goes on its own line, + - function name() is on a line below that, and + - open bracket `{` after that. + - no brackets on `for`, `if`, `while`, etc. statements that only contain one line +- Use `/* comments */` for permanent comments, `// comments` for temporary ones e.g. `TODO`'s or notices +- **Try to make every line 100 characters wide or less.** +- Start source files as `.cc` straight away, even if they're pure **C**. + +### C++-specific guidelines + +- file extension: `.cc`, `.h` +- C++ strings are fine +- Vectors are fine +- Use `printf` and co., not `std::cout`, unless somehow absolutely necessary +- `fstream`s for input/output/log files are fine +- Use C's `struct`s instead of objects unless you really really need an object. +- Use C-style type casting where possible + +TL;DR pretend you're using C with basic modern conveniences. **When in doubt, ask.** + +### Naming and Abbreviations + +The length of a function name, variable name, et cetera should be directly proportional to its importance and lifetime. + +#### Don't + +- abbreviate global variables **EVER**, +- mention the data type in a variable name, +- use a full word where an abbreviation will do + - (especially not in a variable that will die 5 lines later), +- use single-letter abbreviations for anything that lasts more than 15 lines, or +- abbreviate a word when an apt abbreviation does not exist. + +#### Do + +- abbreviate extremely short-lived variables to one letter, + - e.g. `for (int index = 0; index < 10; i++)` -> `for (int i = 0; i < 10; i++)` +- break any rule if following it ruins the readability + +## Source File layout + +```C++ +/* C++ includes */ +#include + +/* C (.h) includes */ +#include + +/* local header includes */ +#include "unicorns.h" + +/* "using" directives */ +using namespace std; + +/* global constants */ +const int life = 42; + +/* global variables */ +int degrees = 90; + +/* function prototypes */ +int div_numb(int n, int d); + +/* main function body */ +int +main(int argc, char *argv[]) +{ + int numerator = 32; + int denominator = 16; + int result; + + puts("What is 32 divided by 16?"); + + result = div_numb(32, 16); + + return 0; +} + +/* other function bodies */ +int +div_numb(int n, int d) +{ + return n / d; +} +``` + diff --git a/client.cc b/client.cc new file mode 100644 index 0000000..cda0188 --- /dev/null +++ b/client.cc @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "disp.h" +#include "log.h" +#include "public.h" + +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 +closeClient() +{ + long e = end1.tv_sec - start1.tv_sec; + + gettimeofday(&end1, NULL); + close(clientSocketDescriptor); + printf("********Session********"); + printf("Bytes written: %i\nBytes read: %i\n", bytesWritten, bytesRead); + printf("Elapsed time: %ld\n secs\n", e); + printf("Connection closed...\n"); +} + +void * +pollForSever(void *args) +{ + waitClientArgs *aaa = static_cast(args); + int socketDescriptor = (int)aaa->auxInt; + char msg[1024]; + while (1) { + 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; + // printf("Server: %s\n"); + 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 + // if(argc != 3) + //{ + // cerr << "Usage: ip_address port" << endl; exit(0); + // } //grab the IP address and port number + // create a message buffer + char msg[1024]; + // setup a socket and connection tools + struct hostent *host = gethostbyname(IP_ADDRESS.c_str()); + sockaddr_in sendSockAddr; + bzero((char *)&sendSockAddr, sizeof(sendSockAddr)); + sendSockAddr.sin_family = AF_INET; + sendSockAddr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host->h_addr_list)); + sendSockAddr.sin_port = htons(PORT_NUM); + clientSocketDescriptor = socket(AF_INET, SOCK_STREAM, 0); + // try to connect... + int status = + connect(clientSocketDescriptor, (sockaddr *)&sendSockAddr, sizeof(sendSockAddr)); + if (status < 0) + writeToFile(logFileName, "Error connecting to socket!"); + 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); +} diff --git a/client.h b/client.h new file mode 100644 index 0000000..edbb52b --- /dev/null +++ b/client.h @@ -0,0 +1,8 @@ +#ifndef CLIENT_H +#define CLIENT_H + +void closeClient(); +void *pollForServer(void *args); +void setupClient(); + +#endif diff --git a/com.txt b/com.txt new file mode 100644 index 0000000..b84058f --- /dev/null +++ b/com.txt @@ -0,0 +1,2 @@ +g++ -pthread -Wall -Wextra -O2 -std=c++17 -lcurses -g -c *.cc +g++ -pthread -Wall -Wextra -O2 -std=c++17 -lcurses -g -o ct *.o diff --git a/disp.cc b/disp.cc new file mode 100644 index 0000000..88c3e04 --- /dev/null +++ b/disp.cc @@ -0,0 +1,55 @@ +#include + +#include + +#include "disp.h" +#include "public.h" + +// clears ncurses rows in a specific region only +void +clearRows(int startingRow, int endingRow) +{ + // preserve the cursor location + int yBefore, xBefore; + getyx(stdscr, yBefore, xBefore); + + for (int i = startingRow; i < endingRow; i++) { + move(i, 0); + clrtoeol(); // clear to end of line + } + + // restore original cursor location + move(yBefore, xBefore); +} + +// display a file using ncurses +int +displayFile(string path, int startLineNum = 0, int numLines = 10) +{ + ifstream file(path); + if (!file) { + return 1; + } else { + clearRows(0, numLines + 1); // clear the chat area + int lineNum = 0; + string line; + + // print each line directly to the screen + int num = 0; + while (getline(file, line) && + num <= numLines + startLineNum + 1) // while there is file content and the + // line number isn't too high + { + if (num >= startLineNum) { + move(lineNum, 0); + printw("%s", line.c_str()); + lineNum++; // increment the row number after + // printing each line + } + num++; + } + move(DEFAULT_CUR_Y, DEFAULT_CUR_X); + refresh(); + return 0; + } +} diff --git a/disp.h b/disp.h new file mode 100644 index 0000000..58e6ecb --- /dev/null +++ b/disp.h @@ -0,0 +1,11 @@ +#ifndef DISP_H +#define DISP_H + +#include + +using namespace std; + +void clearRows(int startingRow, int endingRow); +int displayFile(string path, int startLineNum, int numLines); + +#endif diff --git a/format-configs/.editorconfig b/format-configs/.editorconfig new file mode 100644 index 0000000..ee9f09c --- /dev/null +++ b/format-configs/.editorconfig @@ -0,0 +1,32 @@ +root = true + +[*] +charset = utf-8 +indent_style = tab +indent_size = 8 +tab_width = 8 +end_of_line = lf +insert_final_newline = true + +[*.{c,cc,cpp,h,hpp}] + +# Unbraced single-statement blocks +cpp_remove_braces_for_single_line_control_statements = true +resharper_cpp_remove_braces_for_single_statements = true +resharper_cpp_add_braces_for_single_line_if = false + +# Enforce BSD KNF for function bracess +cpp_new_line_before_open_brace_function = new_line +resharper_cpp_brace_style = next_line +resharper_cpp_function_definition_braces = next_line + +# Enforce K&R for everything else +cpp_new_line_before_open_brace_namespace = same_line +cpp_new_line_before_open_brace_type = same_line +cpp_new_line_before_open_brace_block = same_line +cpp_new_line_before_open_brace_lambda = same_line +cpp_new_line_before_else = false +cpp_new_line_before_catch = false +resharper_cpp_namespace_declaration_braces = end_of_line +resharper_cpp_type_declaration_braces = end_of_line +resharper_cpp_control_transfer_braces = end_of_line diff --git a/format-configs/clang-format.json b/format-configs/clang-format.json new file mode 100644 index 0000000..efc5035 --- /dev/null +++ b/format-configs/clang-format.json @@ -0,0 +1,20 @@ +{ + "BasedOnStyle": "LLVM", + "UseTab": "Always", + "IndentWidth": 8, + "TabWidth": 8, + "ColumnLimit": 120, + "LineEnding": "LF", + "RemoveBracesLLVM": true, + "AlwaysBreakAfterReturnType": "AllDefinitions", + "BreakBeforeBraces": "Custom", + "BraceWrapping": { + "AfterFunction": true, + "AfterClass": false, + "AfterControlStatement": false, + "AfterNamespace": false, + "AfterStruct": false, + "BeforeElse": false, + "BeforeCatch": false + } +} diff --git a/format-configs/clang-format.yml b/format-configs/clang-format.yml new file mode 100644 index 0000000..908da54 --- /dev/null +++ b/format-configs/clang-format.yml @@ -0,0 +1,21 @@ +# BSD KNF funcs + K&R blocks + other stuff +# Requires clang-format >=16 +BasedOnStyle: LLVM # defaults +UseTab: Always +IndentWidth: 8 +TabWidth: 8 +ColumnLimit: 120 +LineEnding: LF # unix + +RemoveBracesLLVM: true # single-statement blocks +AlwaysBreakAfterReturnType: AllDefinitions # KNF functions + +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true # KNF + AfterClass: false # K&R + AfterControlStatement: false # K&R + AfterNamespace: false # K&R + AfterStruct: false # K&R + BeforeElse: false # K&R + BeforeCatch: false # K&R diff --git a/log.cc b/log.cc new file mode 100644 index 0000000..389ebbc --- /dev/null +++ b/log.cc @@ -0,0 +1,44 @@ +#include + +#include "public.h" +#include "log.h" + +// gets the number of lines in a file. returns -1 if there was an error. +int +linesInFile(string path) +{ + ifstream file(path); + if (!file) { + return 1; + } else { + int lineNum = 0; + string line; + + int num = 0; + while (getline(file, line)) + num++; + return num; + } +} + +// appends a line of text to the end of a given file. returns 0 if the file +// existed, 1 if it didn't work +int +writeToFile(string path, string line, bool incLineNum) +{ + ofstream file; + file.open(path, ios_base::app); // open the file in append mode + + if (file.is_open()) { + file << line << endl; + // this probably would help but theres too much broken stuff + // right now to be sure if (incLineNum) + //{ + // linePos++; + // } + return 0; + } else { + // do something if it didn't work + return 1; // i guess that's good enough for now + } +} diff --git a/log.h b/log.h new file mode 100644 index 0000000..d6c6a1a --- /dev/null +++ b/log.h @@ -0,0 +1,9 @@ +#ifndef LOG_H +#define LOG_H + +#include "public.h" + +int linesInFile(string path); +int writeToFile(string path, string line, bool incLineNum); + +#endif diff --git a/main.cc b/main.cc new file mode 100644 index 0000000..4c40d17 --- /dev/null +++ b/main.cc @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include //try to make the program work without this without doing anything awful but do it later + +#include "client.h" +#include "disp.h" +#include "log.h" +#include "public.h" +#include "server.h" + +using namespace std; + +const int PORT_NUM = 8888; +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. +int clientSocketDescriptor; +vector clientSocketDescriptors; // a global vector for storing client + // socket descriptors + +// keep track of the session time using global variables +struct timeval start1, end1; + +// also keep track of the amount of data sent as well +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; + +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 +}; + +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(logFileName) - LOG_LENGTH + 1; + + char *userInput = new char[1024]; + bool exit = false; + + if (mode == 2) { + writeToFile(logFileName, "CLIENT MODE"); + setupClient(); + } else if (mode == 1) { + writeToFile(logFileName, "SERVER MODE"); + setupServer(PORT_NUM); + } + + while (!exit) { + displayFile(logFileName, linePos, LOG_LENGTH); + + // scroll along the screen if and when required so that it stays + // in sync + if (linesInFile(logFileName) > LOG_LENGTH) + linePos++; + + move(12, 0); + printw("> "); + getstr(userInput); + writeToFile(logFileName, userInput); + if (mode == 1) + send(clientSocketDescriptor, (char *)userInput, strlen(userInput), 0); + else + send(clientSocketDescriptor, (char *)userInput, strlen(userInput), 0); + } + + endwin(); + closeServer(); + + return 0; +} diff --git a/public.h b/public.h new file mode 100644 index 0000000..fabef54 --- /dev/null +++ b/public.h @@ -0,0 +1,28 @@ +#ifndef PUBLIC_H +#define PUBLIC_H + +#include + +using namespace std; + +extern const int PORT_NUM; +extern string IP_ADDRESS; +extern const int DEFAULT_CUR_X; +extern const int DEFAULT_CUR_Y; +extern int mode; +extern int serverSocketDescriptor; +extern int clientSocketDescriptor; +extern struct timeval start1, end1; +extern int bytesRead, bytesWritten; +extern const int LOG_LENGTH; +extern int linePos; +extern string logFileName; +extern pthread_t client_wait_thread; +struct waitClientArgs; + +int writeToFile(string path, string line, bool incLineNum = true); +void *waitForClient(void *argss); +void *pollForClient(); +void *pollForSever(void *args); + +#endif diff --git a/server.cc b/server.cc new file mode 100644 index 0000000..2274106 --- /dev/null +++ b/server.cc @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "disp.h" +#include "log.h" +#include "public.h" +#include "server.h" + +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) +{ + waitClientArgs *args = static_cast(argss); + clientSocketDescriptor = + accept(serverSocketDescriptor, (sockaddr *)&args->newSockAddr, &args->newSockAddrSize); + if (clientSocketDescriptor >= 0) { + writeToFile(logFileName, "client connected"); + if (linesInFile(logFileName) > LOG_LENGTH) + linePos++; + displayFile(logFileName, linePos, LOG_LENGTH); + } + delete args; // delete to avoid memory leaks + + return pollForClient(); +} + +void * +pollForClient() +{ + char msg[1024]; + while (1) { + // receive a message from the client (listen) + memset(&msg, 0, sizeof(msg)); // clear the buffer + bytesRead += recv(clientSocketDescriptor, (char *)&msg, sizeof(msg), 0); + writeToFile(logFileName, + msg); // write the client's message to file + if (linesInFile(logFileName) > LOG_LENGTH) + linePos++; + displayFile(logFileName, linePos, LOG_LENGTH); + } + + return nullptr; +} + +// set up a suitable server for this +int +setupServer(int port) +{ + // 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 + serverSocketDescriptor = socket(AF_INET, SOCK_STREAM, 0); + if (serverSocketDescriptor < 0) { + // keeps from bricking the terminal if this happens + endwin(); + + fprintf(stderr, "Error establishing the server socket!\n"); + exit(0); + } + // bind the socket to its local address + int bindStatus = + bind(serverSocketDescriptor, (struct sockaddr *)&servAddr, sizeof(servAddr)); + if (bindStatus < 0) { + // keeps from bricking the terminal if this happens + endwin(); + + fprintf(stderr, "Error binding socket to local address!\n"); + exit(0); + } + 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 + // 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 + auto *aaa = new waitClientArgs{}; // it looks stupid but it works + aaa->newSockAddr = newSockAddr; + aaa->newSockAddrSize = newSockAddrSize; + int rc = pthread_create(&client_wait_thread, nullptr, waitForClient, aaa); + pthread_detach(client_wait_thread); + writeToFile(logFileName, "Server started sucessfully"); + gettimeofday(&start1, NULL); + + return 0; +} + +void +closeServer() +{ + long e = end1.tv_sec - start1.tv_sec; /* the linter freaks out if you + don't save it as a variable */ + + // we need to close the socket descriptors after we're all done + gettimeofday(&end1, NULL); + close(clientSocketDescriptor); + close(serverSocketDescriptor); + + /* Don't just die silently */ + printf("********Session********\n"); + printf("Bytes written: %i\nBytes Read: %i\n", bytesWritten, bytesRead); + printf("Elapsed time: %ld\n secs\n", e); + printf("Connection closed...\n"); +} diff --git a/server.h b/server.h new file mode 100644 index 0000000..7cb058a --- /dev/null +++ b/server.h @@ -0,0 +1,9 @@ +#ifndef SERVER_H +#define SERVER_H + +void *waitForClient(void *argss); +void *pollForClient(); +int setupServer(int port); +void closeServer(); + +#endif