Welcome
Example Code
C and C++
Argument Parsing
Create Subprocess
Create Thread
Is Subprocess Done
Non-Blocking File (Unix)
Mutex (Lock)
TCP Server
Wait For File (Unix)
Python
Non-Blocking Read

Monju System Architects



Code - C++ - TCP Server
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");
}