// header files #include "echoserver.h" // constants // echoserver port is 8888 #define ECHOPORT 8888 #define BUFFER_SIZE 1024 #define MAX_CONNECT_QUEUE 10 // prototypes // main function int main(int argc, char **argv) { // initialize program (variables and structs) bool quitFlag = true; int socketEchoFD; int clientEchoFD; int reuseAddrOpt = 1; int keepAliveOpt = 1; char message[BUFFER_SIZE]; int messageBytes; struct sockaddr_in serverAddr; struct sockaddr_storage clientAddr; socklen_t clientSize; memset(&serverAddr, 0, sizeof(serverAddr)); memset(&clientAddr, 0, sizeof(clientAddr)); // define a TCP socket socketEchoFD = socket(AF_INET, SOCK_STREAM, 0); if(socketEchoFD < 0) { printf("Unable to create the socket.\n"); return -1; } // use the setsockopt function to make the socket accept different configurations // allow for the reuse of the address/bind. setsockopt(socketEchoFD, SOL_SOCKET, SO_REUSEADDR, &reuseAddrOpt, sizeof(reuseAddrOpt)); // also need to set the socket to keepalive using setsockopt setsockopt(socketEchoFD, SOL_SOCKET, SO_KEEPALIVE, &keepAliveOpt, sizeof(keepAliveOpt)); // bind the TCP socket to port 8888 / ECHOPORT serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(ECHOPORT); int bindCheck = bind(socketEchoFD, &serverAddr, sizeof(serverAddr)); if(bindCheck < 0) { printf("Unable to bind the socket to the port or address.\n Is either in use?"); return -1; } // use fnctl to set the non-blocking flag for the socket fcntl(socketEchoFD, F_SETFL, O_NONBLOCK); // the server will now accept client connections by listening. listen(socketEchoFD, MAX_CONNECT_QUEUE); // create a file descriptor set, to keep track of the sockets in use using fd_set and FD_ZERO? fd_set socketList; FD_ZERO(&socketList); // add the socketEchoFD to the file descriptor set using fd_set FD_SET(socketEchoFD, &socketList); // max file descriptor, this will be used to 'find' the socket currently connected int maxFD = socketEchoFD; // while loop that will continue to listen for messages from clients. printf("Echoserver listening on port: %d\n", ECHOPORT); while (quitFlag) { // set of active connections fd_set activeSet = socketList; // use the select() function here to check the set of sockets int selectedFD = select(maxFD+1, &activeSet, NULL, NULL, NULL); // check to make sure select() didn't error out. if(selectedFD == -1) { // printf("\nUnable to select socket to listen to.\n"); return -1; } // for loop that loops up to the max file descriptor. for(int fileIter = 0; fileIter <= maxFD; fileIter++) { // check to see if the file descriptor is in the set of sockets using FD_ISSET() if(FD_ISSET(fileIter, &activeSet)) { // if the server socket is being written to/read from, if(fileIter == socketEchoFD) { // create a client socket using accept clientSize = sizeof(clientAddr); clientEchoFD = accept(socketEchoFD, &clientAddr, &clientSize); // check to see if the client socket is connected (-1) if(clientEchoFD == -1) { printf("\nCould not connect the client to a socket.\n"); return -1; } else { // set the non blocking flag using fnctl fcntl(clientEchoFD, F_SETFL, O_NONBLOCK); // add the client socket to the set of file descriptor sockets FD_SET(clientEchoFD, &socketList); // check to see if the new socket FD is greater than the current max (clientSocket > maxFD) if(clientEchoFD > maxFD) { // if it is, set the new max. maxFD = clientEchoFD; } printf("\nConnected client to socket.\n"); } printf("\nAccepted connection from new client.\n"); } // if the client socket(s) are being written to/read from, else { // grab the data from the client, save to message. messageBytes = recv(fileIter, message, BUFFER_SIZE, 0); // make sure that the connection is still open before attempting to send. if(messageBytes <= 0) // old: messageBytes <= 0 { // if it is not open, close the socket and remove the socket from the socket list using FD_CLR() close(fileIter); FD_CLR(fileIter, &socketList); printf("\nClient has closed connection.\n"); } else { // if it is open, send the message back to the client over the client socket send(fileIter, message, messageBytes, 0); printf("\nMessage has been sent back to client.\n"); } } } } } // close the socket close(socketEchoFD); // profit??? return 0; } // function definitions /* Name: ??? Process: ??? Function Input/Parameters: ??? Function Output/Parameters: ??? Function Output/Returned: ??? Device Input/Device: ??? Device Output/Device: ??? Dependencies: ??? */