Threaded bsd sockets

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Threaded bsd sockets

Beitrag von Halan »

Hey,

ich hab eine kleinen Webserver geschrieben und versuche den jetzt mit threads skalierbar zu machen. Leider funktioniert das ganze nicht. Es scheint wenn der server eine Anfrage ausführt werden alle anderen abgelehnt.

Ich hab etz hier mal den code kopiert. Sollte eigentlich für sich selbst sprechen, fragt einfach wenn was unklar ist.

Code: Alles auswählen

void CWebServer::work()
{
    IServerProcess::work();

    s32 s = conn.accept();

    if (s >= 0)
    {
        try
        {
            boost::function0<s32> f = boost::bind( &CWebServer::serverThread, this, s, conn.getClientAddress());
            boost::thread td(f);
        }
        catch (exception& e)
        {
            Logger->log(ELMT_Warning, "Failed creating thread caused by: ", false);
            Logger->write(e.what());
        }
    }
}

s32 CWebServer::serverThread(s32 socket, string address)
{
    try
    {
        //! CWebServer is also the handler
        //! Debugging is disabled by default
        CHttp http(this, address, false);

        http.parseRequest(socket);

        conn.close(socket);

        return 0;
    }
    catch (exception& e)
    {
        Logger->log(ELMT_Warning, "Failed processing Request caused by: ", false);
        Logger->write(e.what());

        return -1;
    }
}
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Jörg »

Mit welchen Parametern rufst Du listen() auf dem Socket von 'conn' auf ?
Es scheint wenn der server eine Anfrage ausführt werden alle anderen abgelehnt.
Es scheint klingt als ob Du Dir nicht sicher bist...was sind die Symptome?
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Halan »

Okay, ein paar der Probleme hab ich jetzt abgefangen weil ich wohl EWOULDBLOCK nicht gehandelt hab.

Aber trotzdem bekomme ich manchmal wenn ich mehrmals hintereinander anfrage in Firefox:
"Verbindung unterbrochen: Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde."

EDIT: Okay ich denk ich hab das Problem:
Es kann ja sein dass der Client disconnected (send/recv also 0 zurückgeben) ich rufe aber trotzdem conn.close(socket); auf. Jetzt kann der fd ja schonwieder vergeben sein oder nicht? Und dann schließe ich die neueVverbindung.
Jetzt muss ich nur überlegen wie ich das fixe.

Jetzt spiel ich mit dem gedanken das ganze über fork() zu machen. Mit threads hab ich iwie immer nur probleme. Oder select() und die threads weg zu lassen, aber dann scheint das ganze nicht skalierbar genug :(
odenter
Establishment
Beiträge: 207
Registriert: 26.02.2009, 11:58

Re: Threaded bsd sockets

Beitrag von odenter »

Ohne Threads wirds nicht gehen.

Wenn Du auf Port 80 horchst, dann machst Du bei jeder eingehenden Verbindung einen neuen Thread in dem jeder einzelne Client behandelt wird. Wenn der Client (oder wer auch immer) die Verbindung beendet, dann beendest auch Deinen Thread.

Du brauchst also ne Klasse ala

Code: Alles auswählen

class CClientHandler {
  private:
    bool isRunningValue = false;

  public:
    CClientHandler(Socket s) {
    }

    void Start() {
      isRunningValue = true;

      while (isRunningValue) {
      }
    }

    bool IsRunning() {
    }
}
Und die Start-Methode dann in einem Thread aufrufen und darin halt die Kommunikation machen, dann sollte alles ohne Probleme gehen.
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Halan »

danke für die antwort odenter.

Das ist ja im Prinzip das was ich schon mache.

Ich habe einen socket der nach einkommen verbindungen "guckt". Wenn ein client verbindet erstelle ich einen neuen thread mit einer handler klasse (=CHttp) udn übergebe ihr den socket.

Das ganze funktioniert auch ziehmlcih gut solang ich nicht während dem laden einer seite refreshe. Ich denke dann bricht der browser aprupt die verbindung ab. Iwas geht da mit den filedescriptors schief. Gibt es irgendwo ein tutorial das die thematik "sockets und threads" behandelt?
Das typische linux szenario wäre fork() aber das wollte ich in diesem fall eigentlich nicht verwenden :(
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Jörg »

Halan hat geschrieben: Es kann ja sein dass der Client disconnected (send/recv also 0 zurückgeben) ich rufe aber trotzdem conn.close(socket); auf. Jetzt kann der fd ja schonwieder vergeben sein oder nicht?
Nein, der fd wird fruehestens dann wiederverwendet, wenn er geschlossen wurde.
Hast Du beachtet, dass beim send u.U. nicht alles auf einmal uebertragen wird? Wenn du das nicht abfaengst, sondern einfach weitermachst, schliesst Du eine Verbindung, bei der die Gegenseite (Browser) noch Daten erwartet.
Das umsteigen auf fork wird in deinem Falle das Problem nicht loesen, das handling der sockets bleibt davon unberuehrt.
odenter
Establishment
Beiträge: 207
Registriert: 26.02.2009, 11:58

Re: Threaded bsd sockets

Beitrag von odenter »

Halan hat geschrieben: Das ganze funktioniert auch ziehmlcih gut solang ich nicht während dem laden einer seite refreshe. Ich denke dann bricht der browser aprupt die verbindung ab. Iwas geht da mit den filedescriptors schief. Gibt es irgendwo ein tutorial das die thematik "sockets und threads" behandelt?
Das typische linux szenario wäre fork() aber das wollte ich in diesem fall eigentlich nicht verwenden :(
Wäre ja auch logisch wenn der Browser die Verbindung beendet. Du hast dem Browser ja gesagt er soll alles neu anfordern.

Man kann doch abfragen in welchem Status sich der Socket befindet. Sende halt nur Daten, wenn die Verbindung noch da ist.
Alternativ könnte man erstmal ein Try / Catch umzubauen und den Fehler einfach wegfischen, ist aber nicht gerade optimal. :)
Halan
Beiträge: 73
Registriert: 22.01.2005, 21:47
Benutzertext: programmiersüchtig
Echter Name: Kai Mast
Wohnort: Freak City
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Halan »

Hab das ganze jetzt mit fork realisiert aber iwie funktioniert das noch nicht ganz (teile der Seite laden nie fertig)

Code: Alles auswählen

void CWebServer::work()
{
    IServerNode::work();

    s32 s = conn.accept();

    //! If the filedescriptor is valid we start a new thread
    if (s >= 0)
    {
        Logger->log(ELMT_Info, "New Web Request. Forking...");

        DatabaseManager->deactivate();

        s32 res = fork();

        if(res == 0)
        {
            DatabaseManager->activate();

            //! TODO: keep connections. ATM we just process one request and close the thread
            Logger->setLogToFile(false);
            Logger->setName("WebFork");
            this->writeUpdatesToDatabase(false);

            CHttp http(this, conn.getClientAddress(), false);
            http.parseRequest(s);

            conn.close(s);

            exit(0);
        }
        else if(res < 0)
            Logger->log(ELMT_Warning, "Something went wrong forking");

        DatabaseManager->activate();
    }

    //! Update the sessions
    //! We disconnect them after a 30 minute timeout
    SessionManager->work();
}
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Jörg »

conn.close(s); <-- was macht das ? Nur close() auf dem Socket aufrufen?

Dann koenntest Du in Probleme laufen, weil Du fork() verwendet hast, die genau in Symptomen resultieren, die Du beschreibst.
Versuch mal, vorher ein shutdown() auf dem Socket zu machen. close() laesst den Socket naemlich fuer andere Prozesse offen....
Benutzeravatar
kimmi
Moderator
Beiträge: 1405
Registriert: 26.02.2009, 09:42
Echter Name: Kim Kulling
Wohnort: Luebeck
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von kimmi »

Ich fand die folgende Seite recht nützlich:
http://www.beej.us/guide/bgnet/output/h ... index.html

Gruß Kimmi
Jörg
Establishment
Beiträge: 296
Registriert: 03.12.2005, 13:06
Wohnort: Trondheim
Kontaktdaten:

Re: Threaded bsd sockets

Beitrag von Jörg »

Leider erwaehnt diese aber mit keinem Wort das Verhalten von sockets im Falle von fork().

Daher, wenn's mal klemmt: http://www.faqs.org/faqs/unix-faq/socket/

Joerg
Antworten