예제 #1
0
/**
 *  Hauptschleife.
 *
 *  @author FloSoft
 */
void LobbyClient::Run(void)
{
    if(state == CS_STOPPED)
        return;

    SocketSet set;

    // erstmal auf Daten überprüfen
    set.Clear();

    // zum set hinzufügen
    set.Add(socket);
    if(set.Select(0, 0) > 0)
    {
        // nachricht empfangen
        if(!recv_queue.recv(socket))
        {
            LOG.lprintf("Receiving Message from server failed\n");
            ServerLost();
            return;
        }
    }

    // nun auf Fehler prüfen
    set.Clear();

    // zum set hinzufügen
    set.Add(socket);

    // auf fehler prüfen
    if(set.Select(0, 2) > 0)
    {
        if(set.InSet(socket))
        {
            // Server ist weg
            LOG.lprintf("Error on socket to server\n");
            ServerLost();
            return;
        }
    }

    // maximal 10 Pakete verschicken
    if(!send_queue.send(socket, 10))
    {
        ServerLost();
        return;
    }

    // recv-queue abarbeiten
    while(recv_queue.count() > 0)
    {
        recv_queue.front()->run(this, 0xFFFFFFFF);
        recv_queue.pop();
    }
}
예제 #2
0
/**
 *
 *
 *  @author FloSoft
 */
Message* Message::recv(Socket& sock, int& error, bool wait, Message * (*createfunction)(unsigned short))
{
    error = -1;

    unser_time_t time = TIME.CurrentTick();

    unser_time_t timeout = time;
    unsigned int received;
    SocketSet set;

    while(true)
    {
        // Warten wir schon 5s auf Antwort?
        if(time - timeout > 15000)
            wait = false;

        time = TIME.CurrentTick();

        // SocketSet "saubermachen"
        set.Clear();

        // Socket hinzufgen
        set.Add(sock);

        // liegen Daten an?
        int retval = set.Select(0, 0);

        if(retval <= 0)
        {
            if(wait)
                continue;

            if(retval != -1)
                error = 0;

            return NULL;
        }

        // liegen diese Daten an unserem Socket, bzw wieviele Bytes liegen an?
        if(!set.InSet(sock) || sock.BytesWaiting(&received) != 0)
        {
            if(wait)
                continue;

            error = 1;
            return NULL;
        }

        // socket ist geschlossen worden
        if(received == 0)
            return NULL;

        // haben wir schon eine vollständige nachricht? (kleinste nachricht: 6 bytes)
        if(received < 6)
        {
            if(wait)
                continue;

            error = 2;
            return NULL;
        }
        break;
    }

    int read = -1;

    char block[6];
    unsigned short* id = (unsigned short*)&block[0];
    unsigned int* length = (unsigned int*)&block[2];

    // block empfangen
    read = sock.Recv(block, 6, false);
    if(read != 6)
    {
        LOG.write("recv: block: only got %d bytes instead of %d, waiting for next try\n", read, 6);
        if(read != -1)
            error = 3;

        return NULL;
    }

    read = sock.BytesWaiting();

    static unsigned int blocktimeout = 0;
    if(read < (signed)((*length) + 6) )
    {
        ++blocktimeout;
        LOG.write("recv: block-waiting: not enough input (%d/%d) for message (0x%04X), waiting for next try\n", read, (*length) + 6, *id);
        if(blocktimeout < 120 && read != -1)
            error = 4;

        return NULL;
    }
    blocktimeout = 0;

    // Block nochmals abrufen (um ihn aus dem Cache zu entfernen)
    read = sock.Recv(block, 6);
    if(read != 6)
    {
        LOG.lprintf("recv: id,length: only got %d bytes instead of %d\n", read, 2);
        return NULL;
    }

    Message* msg = createfunction(*id);
    if(!msg)
        return NULL;

    // Daten abrufen
    msg->recv(sock, *length);

    return msg;
}
예제 #3
0
/**
 *  verarbeitet alle Nachrichten der Clients.
 *
 *  @author FloSoft
 */
bool LobbyServer::ProcessMessages()
{
    SocketSet set;

    // In einem SocketSet alle Clients hinzufügen und gucken, ob etwas empfangen wurde
    for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it)
    {
        LobbyPlayer& p = it->second;

        if(!p.isFree())
            p.addToSet(set);
    }

    if(set.Select(0, 0) > 0)
    {
        for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it)
        {
            LobbyPlayer& p = it->second;

            if(p.inSet(set) && !p.Receive())
                Disconnect(p);
        }
    }

    set.Clear();

    // In einem SocketSet alle Clients hinzufügen und gucken, ob fehler aufgetreten sind
    for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it)
    {
        LobbyPlayer& p = it->second;

        if(!p.isFree())
            p.addToSet(set);
    }

    if(set.Select(0, 2) > 0)
    {
        LOG.write("Error on Sockets\n");

        for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it)
        {
            LobbyPlayer& p = it->second;

            if( p.inSet(set) )
            {
                LOG.write("Player %d: Connection lost\n") % p.getId();
                Disconnect(p);
            }
        }
    }

    // Nachrichten-Queues der Spieler abschicken (max 10 Nachrichten pro Spieler pro Runde)
    for(LobbyPlayerMapIterator it = players.begin(); it != players.end(); ++it)
    {
        LobbyPlayer& p = it->second;

        if(!p.Send())
            Disconnect(p);
        else
            p.Run(this);
    }

    return true;
}