From 3370b59fe2c9544fddebb1281505ddec3d22c0e1 Mon Sep 17 00:00:00 2001 From: Bjørn Lindeijer Date: Mon, 18 Apr 2005 12:55:41 +0000 Subject: Server now succesfully listens for connections, accepts them, receives some data in a crude way and cleans up connection on client disconnect. --- src/connectionhandler.cpp | 107 ++++++++++++++++++++++++++++++++++++++++++++++ src/connectionhandler.h | 12 ++++++ src/netcomputer.cpp | 11 +++++ src/netcomputer.h | 13 +++--- src/netsession.cpp | 42 +++++++----------- 5 files changed, 151 insertions(+), 34 deletions(-) diff --git a/src/connectionhandler.cpp b/src/connectionhandler.cpp index c843140c..953f5c15 100644 --- a/src/connectionhandler.cpp +++ b/src/connectionhandler.cpp @@ -22,11 +22,118 @@ */ #include "connectionhandler.h" +#include "netsession.h" + +#define MAX_CLIENTS 1024 ConnectionHandler::ConnectionHandler() { } +void ConnectionHandler::startListen(ListenThreadData *ltd) +{ + // Allocate a socket set + SDLNet_SocketSet set = SDLNet_AllocSocketSet(MAX_CLIENTS); + if (!set) { + printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError()); + exit(1); + } + + // Add the server socket to the socket set + if (SDLNet_TCP_AddSocket(set, ltd->socket) < 0) { + printf("SDLNet_AddSocket: %s\n", SDLNet_GetError()); + exit(1); + } + + // Keep checking for socket activity while running + while (ltd->running) + { + int numready = SDLNet_CheckSockets(set, 100); + + if (numready == -1) + { + printf("SDLNet_CheckSockets: %s\n", SDLNet_GetError()); + // When this is a system error, perror may help us + perror("SDLNet_CheckSockets"); + } + else if (numready > 0) + { + printf("%d sockets with activity!\n", numready); + + // Check server socket + if (SDLNet_SocketReady(ltd->socket)) + { + TCPsocket client = SDLNet_TCP_Accept(ltd->socket); + if (client) + { + // Add the client socket to the socket set + if (SDLNet_TCP_AddSocket(set, client) < 0) { + printf("SDLNet_AddSocket: %s\n", SDLNet_GetError()); + } + else { + NetComputer *comp = new NetComputer(this); + clients[comp] = client; + computerConnected(comp); + printf("%d clients connected\n", clients.size()); + } + } + } + + // Check client sockets + std::map::iterator i; + for (i = clients.begin(); i != clients.end(); ) + { + NetComputer *comp = (*i).first; + TCPsocket s = (*i).second; + + if (SDLNet_SocketReady(s)) + { + char buffer[1024]; + int result = SDLNet_TCP_Recv(s, buffer, 1024); + if (result <= 0) + { + SDLNet_TCP_DelSocket(set, s); + SDLNet_TCP_Close(s); + computerDisconnected(comp); + delete comp; + comp = NULL; + } + else + { + buffer[result] = 0; + printf("Received %s\n", buffer); + } + } + + // Traverse to next client, possibly deleting current + if (comp == NULL) { + std::map::iterator ii = i; + ii++; + clients.erase(i); + i = ii; + } + else { + i++; + } + } + } + } + + // - Disconnect all clients (close sockets) + + SDLNet_FreeSocketSet(set); +} + +void ConnectionHandler::computerConnected(NetComputer *comp) +{ + printf("A client connected!\n"); +} + +void ConnectionHandler::computerDisconnected(NetComputer *comp) +{ + printf("A client disconnected!\n"); +} + void ConnectionHandler::registerHandler( unsigned int msgId, MessageHandler *handler) { diff --git a/src/connectionhandler.h b/src/connectionhandler.h index bc5f0965..ab01dc2c 100644 --- a/src/connectionhandler.h +++ b/src/connectionhandler.h @@ -28,6 +28,10 @@ #include "netcomputer.h" #include "packet.h" #include +#include + +// Forward declaration +class ListenThreadData; /** * This class represents the connection handler interface. The connection @@ -42,6 +46,13 @@ class ConnectionHandler */ ConnectionHandler(); + /** + * Starts listening to the server socket. It accepts new connections + * and receives data from connected clients. All computers are + * disconnected when listening stops. + */ + void startListen(ListenThreadData *ltd); + /** * Called when a computer connects to a network session. */ @@ -72,6 +83,7 @@ class ConnectionHandler private: std::map handlers; + std::map clients; }; #endif diff --git a/src/netcomputer.cpp b/src/netcomputer.cpp index 89317dc0..79110fd4 100644 --- a/src/netcomputer.cpp +++ b/src/netcomputer.cpp @@ -23,3 +23,14 @@ #include "netcomputer.h" + +NetComputer::NetComputer(ConnectionHandler *handler): + handler(handler) +{ +} + +void NetComputer::disconnect(const std::string &reason) +{ + // Somehow notify the netsession listener about the disconnect after + // sending this computer a disconnect message containing the reason. +} diff --git a/src/netcomputer.h b/src/netcomputer.h index 02948207..1a73d675 100644 --- a/src/netcomputer.h +++ b/src/netcomputer.h @@ -25,10 +25,11 @@ #define _TMW_SERVER_NETCOMPUTER_ #include "packet.h" +#include #include // Forward declaration -class NetSession; +class ConnectionHandler; /** * This class represents a known computer on the network. For example a @@ -40,12 +41,7 @@ class NetComputer /** * Constructor. */ - NetComputer(NetSession *session); - - /** - * Returns the netsession that the computer is attached to. - */ - NetSession *getSession(); + NetComputer(ConnectionHandler *handler); /** * Returns true if this computer is disconnected. @@ -66,6 +62,9 @@ class NetComputer */ void send(Packet *p); //void send(Packet *p, bool reliable = true); + + private: + ConnectionHandler *handler; }; #endif diff --git a/src/netsession.cpp b/src/netsession.cpp index a617c105..f4f77214 100644 --- a/src/netsession.cpp +++ b/src/netsession.cpp @@ -23,35 +23,16 @@ #include "netsession.h" -#define MAX_CLIENTS 1024 - +/** + * This function is the new thread created to listen to a server socket. It + * immediately passes control over to the connection handler instance that will + * deal with incoming connections and data. + */ int startListenThread(void *data) { ListenThreadData *ltd = (ListenThreadData*)data; - - // Allocate a socket set - SDLNet_SocketSet set = SDLNet_AllocSocketSet(MAX_CLIENTS); - if (!set) { - printf("SDLNet_AllocSocketSet: %s\n", SDLNet_GetError()); - exit(1); - } - - // Add the server socket to the socket set - if (SDLNet_TCP_AddSocket(set, ltd->socket) < 0) { - printf("SDLNet_AddSocket: %s\n", SDLNet_GetError()); - exit(1); - } - - // Keep checking for socket activity while running - while (ltd->running) - { - int numready = SDLNet_CheckSockets(set, 1000); - printf("numready: %d\n", numready); - } - - SDLNet_FreeSocketSet(set); - + ltd->handler->startListen(ltd); return 0; } @@ -73,10 +54,16 @@ void NetSession::startListen(ConnectionHandler *handler, Uint16 port) ListenThreadData *data = new ListenThreadData(); - data->address.host = INADDR_ANY; - data->address.port = port; data->handler = handler; data->running = true; + + // Fill in IPaddress for opening local server socket + if (SDLNet_ResolveHost(&data->address, NULL, port) == -1) { + printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + exit(6); + } + + // Attempt to open the local server socket data->socket = SDLNet_TCP_Open(&data->address); if (!data->socket) { @@ -84,6 +71,7 @@ void NetSession::startListen(ConnectionHandler *handler, Uint16 port) exit(3); } + // Start the listening thread data->thread = SDL_CreateThread(startListenThread, data); if (data->thread == NULL) { -- cgit v1.2.3-60-g2f50