Download: |
tcpServer.cpp
(the linked-to file is properly tabbed)
|
Requires: |
file.h, mutex.h, mutex.cpp, parseArgument.h, parseArgument.cpp, signal.h, signal.cpp, socket.h, socket.cpp, systemSignal.h, systemSignal.cpp, thread.h, thread.cpp, waitForDescriptor.cpp
|
// Copyright (c) 2007, Monju System Architects
//
// Released under the Monju-Public copyright license:
//
// Permission is hereby granted, free of charge, to any person or entity
// obtaining a copy of this software and associated documentation files
// (the "Software"), to deal in the Software without restriction,
// including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies and modifications
// of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of published, sold, or
// ownership-transferred versions of the Software. The notices are not
// required for binary-only releases or binary-only derivatives of the
// Software, or documentation provided with binary-only releases and
// binary-only derivatives.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// INCLUDES.
#ifndef _WIN32
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include "public/file.h"
#include "public/mutex.h"
#include "public/parseArgument.h"
#include "public/signal.h"
#include "public/socket.h"
#include "public/subprocess.h"
#include "public/systemSignal.h"
#include "public/thread.h"
// MACROS.
#ifdef DEBUG
#define DEBUG_NOTICE(...) fprintf(stderr, __VA_ARGS__); fflush(stderr);
#else
#define DEBUG_NOTICE(...)
#endif
// FUNCTION DECLARATIONS.
void cleanUp(SOCKET_TYPE socket, bool wasInitialized);
void handleConnection(SOCKET_TYPE socket);
void* handleConnectionThread(void* pVoidSocket);
// handleConnection()
void handleConnection(SOCKET_TYPE socket) {
// CREATE THE THREAD.
int* pSocket = new int;
*pSocket = socket;
try{
createThread(handleConnectionThread, (void*) pSocket);
}
catch (...){
// DELETE THE SOCKET.
delete pSocket;
// THROW AN ERROR.
throw("pthread_create() failed.");
}
}
// handleConnectionThread()
void* handleConnectionThread(void* pVoidSocket) {
DEBUG_NOTICE("A thread is handling the connection.\n");
// GET OUR SOCKET.
SOCKET_TYPE* pSocket = (SOCKET_TYPE*) pVoidSocket;
// DO CONNECTION WORK.
try {
writeSocket(*pSocket, "Hi\n");
DEBUG_NOTICE("\"Hi\" was sent to the socket.\n");
int amount = 500;
char pBuffer[502];
for (amount=500; readSocket(*pSocket, pBuffer, &amount, 3); amount=500) {
pBuffer[amount] = '\0';
DEBUG_NOTICE("Received: %s\n", pBuffer)
}
}
catch(const char* pErrorString) {
DEBUG_NOTICE("%s", pErrorString);
}
catch(...) {
}
// CLOSE AND FREE THE SOCKET.
closeSocket(*pSocket);
delete pSocket;
DEBUG_NOTICE("The socket was closed (3 seconds of inactivity.\n");
return NULL;
}
// runTcpServer()
int runTcpServer(int port=51234) {
// DECLARATIONS.
SOCKET_TYPE listeningSocket;
bool wasListeningSocketCreated = false;
// DO SETUP.
try {
// START UP SOCKETS ON WINDOWS.
#ifdef _WIN32
WSADATA wsaData;
if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)) {
throw("WSAStartup() failed.");
}
#endif
// CREATE THE SOCKET.
listeningSocket = createTcpSocket();
wasListeningSocketCreated = true;
// BIND.
DEBUG_NOTICE("Binding to port: %d...", port);
bindSocket(listeningSocket, port);
DEBUG_NOTICE(" done.\n");
// SET NON BLOCKING.
setNonBlockingSocket(listeningSocket);
// LISTEN.
DEBUG_NOTICE("LISTENING on port: %d...\n", port);
listenSocket(listeningSocket);
// ACCEPT.
SIGNAL_TYPE exitSignal = getExitSignal();
while (!isSignalSet(exitSignal)) {
// ACCEPT A CONNECTION.
CLIENT_ADDRESS_TYPE address;
SOCKET_TYPE newSocket;
if (!acceptSocket(listeningSocket, &newSocket, &address)) {
msleep(1);
continue;
}
DEBUG_NOTICE("\nSocket accepted.\n");
// HANDLE THE NEWLY CONNECTED SOCKET.
handleConnection(newSocket);
}
}
catch(...) {
cleanUp(listeningSocket, wasListeningSocketCreated);
throw;
}
cleanUp(listeningSocket, wasListeningSocketCreated);
}
// cleanUp()
void cleanUp(SOCKET_TYPE listeningSocket, bool wasListeningSocketCreated) {
// CLEAN UP.
DEBUG_NOTICE("Cleaning up...");
if (wasListeningSocketCreated) {
closeSocket(listeningSocket);
}
DEBUG_NOTICE(" done.\n");
}
|