staging.inyokaproject.org

Frage zur Socketprogrammierung und Threads

Status: Ungelöst | Ubuntu-Version: Ubuntu Budgie 17.10 (Artful Aardvark)
Antworten |

momooo

Anmeldungsdatum:
11. Oktober 2017

Beiträge: 23

Hallo liebe Forenbesucher,

wie im Titel schon erwähnt hätte ich eine Frage zur Socket Programmierung.

Soweit ich weiß, blockiert der accept Befehl solange bis ein neuer Client sich verbindet. Um das zu umgehen, also das Blocken zu verhindern, war es meine Idee diese durch select zu realisieren.

Also meine Idee ist es durch select zu schauen ob neue Clients sich verbinden wollen. Falls das zutrifft also wenn ein Client sich verbindet, werden die Daten (vorallem file descriptor) des Clients in einer Struktur gespeichert und ein neuer Thread erzeugt.

Falls doch kein neuer Client versucht sich zu verbinden, soll ein Thread laufen (also ein bereits verbundener Client in einem Thread abgearbeitet werden).

Ich hätte ungefähr an sowas gedacht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20

while (1){

FD_ZERO(&new_client);
FD_SET (&fd_accept_new, &new_client);

if((fd_accept_new = accept(fd_socket,.....)) < 0)
     perror(...)

  if((select(max_fd_select + 1, &new_client,... )) < NULL)
   perrer("Select");

  if(FD_ISSET(fd_accept_new, &new_client)){
    //den neuen file descriptor in eine Struktur speichern
    //z.B: SocketFd_client[0].fd = fd_accept_new
  } else
    

   Pthread_create(&tid, Null, &irgendwas, (void *) SocketFd_client)
}

Ich will im Grunde schauen, ob ein neuer Client sich verbinden will, wenn ja will ich sein File Deskriptor in eine Client-Struktur speichern und einen neuen Thread starten, wenn nicht sollen die Threads laufen, welche die Clients aberbeiten.

Irgendwie stehe ich voll am Schlauch und weiß nicht wie ich die Sache am besten angehen soll, ich habe irgendwie den Überblick verloren und hoffe ihr könnt mir da weiter helfen.

Lg

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@momooo: Ich verstehe das mit dem select() nicht so ganz‽ Also warum? Das kann doch ruhig blockieren, denn eventuell schon vorhandene Threads laufen doch parallel weiter. Das ist doch gerade der Sinn von Threads.

momooo

(Themenstarter)

Anmeldungsdatum:
11. Oktober 2017

Beiträge: 23

Ich hatte mir gedacht, solange accept blockt sollen die Threads laufen, wenn aber jetzt ein neuer Client dazu kommt, soll sein file descriptor gespeichert werden und dadurch ein neuer Thread erstellt werden, welcher dem neuen Client zugeorndet ist...das war eigentlich meine Idee und ich dachte das geht am einfachsten wenn ich select verwende...

Ich bin noch am einlernen und deshalb tu ich mir da sehr schwer, vorallem weiß ich nicht oder kann mir nicht vorstellen wie ich das aufbauen soll deshalb wäre für Ratschläge für weitere angehensweisen sehr sehr dankbar...

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@momooo: Einfacher geht es wie gesagt ohne select(). Ich verstehe auch immer noch nicht was Du an der Stelle damit bezwecken willst. select() verwendet man wenn man keine Threads pro Client verwendet, sondern alle Clients im gleichen Thread verarztet, oder im jeweiligen Client-Thread um dort Ein- und Ausgabe ”parallel” erledigen zu können, ohne das man für beides einen eigenen Thread braucht.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Wir haben ja jetzt nur wenig Kontext. Ich nehme mal an, dass Du einen Server schreiben willst, der eigentlich nur auf Anfragen von Clients wartet und diese dann abarbeitet. Für das Szenario kannst Du einfach im Main-Thread den Socket aufmachen und in einer Endlosschleife blockierend auf Verbindungsversuche warten. Wenn sich ein Client verbindet, startest Du einen Thread mit dem Filedeskriptor als Eingabe und der initialisiert dann alle nötigen Datenstrukturen und bearbeitet die Anfragen. Möglicherweise ist es sinnvoll, erst ein paar Prüfungen im Main-Thread zu machen (z.B. darf ein Client sich von dieser IP verbinden?) bevor Du den Arbeitsthread startest.

In der Praxis wirst Du natürlich etwas mehr brauchen, z.B. will man sicherlich Signale empfangen und wenn z.B. ein SIGTERM gekommen ist, den Server herunter fahren - ggf. nachdem alle aktuellen Anfragen bearbeitet wurden. Das schwierige dabei könnte sein, die Threads aufzuwecken, damit sie mitbekommen, was passiert ist. Irgendwer schläft ja immer. 😉 Da kenne ich mich bei PThreads zu wenig aus, aber nachdem das in Java geht, gehe ich davon aus, dass es da auch etwas von Ratiopharm C gibt (siehe hier).

Abhängig vom Protokoll, das über den Socket gesprochen wird, können auch noch modifizierte Varianten sinnvoll sein, z.B. eine Queue mit Antworten, die von einem separaten Thread auf den Socket geschrieben werden, damit man bereits die nächste Anfrage bearbeiten kann, wenn eine neue Anfrage reinkommt. Bei HTTP ist das z.B. nicht zulässig, so dass man mit einem Thread auskommt, der immer zwischen lesen, bearbeiten, schreiben wechselt.

Wenn Du richtig viele (sagen wir mal >10000) gleichzeitige Verbindungen bearbeiten willst, darfst Du auf jeden Fall nicht mehr einen oder zwei Threads pro Verbindung haben, sondern musst einen Thread nutzen, um mehrere Sockets zu bedienen. Dann brauchst Du auf jeden Fall select() & Co.

momooo

(Themenstarter)

Anmeldungsdatum:
11. Oktober 2017

Beiträge: 23

Vielen Dank für die vielen Antworten ☺ dann verwende ich auch kein select ergibt eh mehr Sinn aber wann macht es überhaupt Sinn ein select in dem Kontext zu verwenden?

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4735

@momooo: Na das haben wir doch geschrieben: select() macht Sinn wenn man mehrere Verbindungen ohne Thread pro Verbindung bedienen will. Entweder für einen Client wenn es ein Vollduplex-Protokoll ist, oder für eine Gruppe von Clients, oder gar alle Clients.

Antworten |