Socket-Server soll mehrere Clients akzeptieren!!!
-
Wenn du CAsyncSocket benutzt brauchst du nur einen einzigen Thread.
-
du kannst CWinThread-objekte auch in einem CObArray speichern (in das CObArray kannst du alle klassen einfügen, die von CObject abgeleitet sind)
warum willst du denn eigentlich was mit threads machen? vielleicht kannst du das anders machen (vielleicht einfacher)
@Unix-Tom: arbeitet CAsyncSocket nicht mit einem eigenen Thread? kann sein das ich falsch liegen. aber wenn nicht dann wird für jedes objekt der socketklasse automatisch ein eigener thread gestartet ohne das man es merken würde.
-
Also habe folgende Aufgaben für den Server und Client.
Clients sollen auf den Server zugreifen und sich im ersten Schritt registrieren und ihre Informationen senden. Danach wird die passende Information auf dem Server gesucht und zurück gesendet.
Mit einem Client läuft es auch.
Ich habe auch schon daran gedacht alle anderen Clients solange zu blockieren bis der gerade aktive Client fertig ist.
Doch wird das bei einer größeren Anzahl von Clients nicht mehr gut funktionieren (Clients müssen zu lange warten).
Daher dachte ich an Threads.
So könnten mehrere Clients zum Server verbinden und dort ihre Arbeit verrichten bis sie fertig sind.
Die Frage von Red Skall an Unix-Tom ist gut und ist von Bedeutung für mich, denn entweder muss ich noch Threads erstellen für jeden verbundenen Client oder sie werden automatisch erstellt.
Mfg
-
in diesem fall sind threads doch gar nicht nötig.
wenn der client etwas an den server sendet wird dort OnReceive() der CMySocket klasse aufgerufen. nach dem beispiel von visual studio in 21 tagen wird dort die dialogfeld hauptklasse aufgerufen.
dann gehst du wie folgt vor:
client-abhängige werden im sopcket objekt gespeichert (du legst in deiner CMySocket klasse z.b. eine variable 'int iID').
wenn du jetzt aus deiner socket klasse heraus die funktionen OnAccept(), OnReceive(), ... deiner dialogfeld klasse aufrufst, übergibt du diesen funktionen einfach die adresse deines sockets, z.B.:
m_ParentDlg->OnAccept(iErrorCode, this);dann kannst du im hauptdialogfeld ganz einfach und abhängig vom jeweiligen client auf das ereignis reagieren. da du hier über die ID 'iID' sieht welcher client gerade eine anfrage sendet.
die id vergibst du dann am besten in OnAccept().
das kann man auch alles anders machen. aber so oder so ähnlich wirds wohl ganz gut laufen, hoffe ich

-
Du hast schon recht.
Doch leider ist mein Server Programm nicht so einfach wie das Beispiel Programm aus dem Buch(es basiert zwar auf der gleichen kommunikation, dass ist aber alles).
Klar möchte ich gerne ohne threads arbeiten doch glaube ich nicht das das geht.
Ich verstehe, das ich OnReceive und OnAccept mit Hilfe einer ID immer herausfinden kann wer gerade auf mich zugreift.
Doch die Arbeiten die der Client auf dem Server verrichten soll sind etwas komplizierter als einfach nur einen Text anzuzeigen. So muss der Server in einer Datenbank die ID suchen und die gesendeten Daten des Clients vergleichen.
Danach einige Funktionen durchlaufen und sendet dann am Ende eine Information zurück.
Und diese Funktionen auf dem Server müssen, damit der nächste Client nicht warten muss gleichzeitig ausgeführt werden oder?
Ich hoffe du versteht mich. Wenn ich dich falsch verstanden habe oder zu blöd war um es zu verstehen tut es mir leid, dann versuch es bitte nochmal.
-
die funktionen können "gleichzeitig" aufgerufen werden. da brauchst du dir keine sorgen drum machen. ich glaube du denkst:
wenn der server gerade eine funktion abarbeitet, z.B. OnReceive() und er gerade so in der mitte der funktion ist kann ein anderer client nicht diese funktion aufrufen, oder ? das stimmt auf jeden fall nicht.
das läuft alles parallel. du kannst also dich in der funktion auf einen einzigen client konzentrieren. du hast ja die adresse vom socket objekt (client) und bearbeitest genau diesen client im funktionsaufruf. wenn gleichzeitig ein anderes socket-objekt die funktion aufruft werden diese abläufe nicht gestört. im speichert wird das getrennt gemacht.
-
Das wusste ich wirklich nicht.
Doch das gilt nur für OnReceive aber nicht für die anderen Funktionen auf dem Server (oder ?) wie z.b. die Funktion die auf die Datenbank zugreift und alle Datensätze durchläuft bis es die passenden Informationen findet die in OnReceive gesendet wurden oder?
Des weitern bin ich mir bei OnReceive auch nicht so sicher, denn ich bekomme von jedem Client in einer bestimmten Reihenfolge informationen (z.b. Name, Vorname, Adresse, usw.) und speichere diese ab. Wenn jetzt ein anderer Client verbindet und zur gleichen Zeit sendet kommt die Reihenfolge ganz durcheinander oder nicht?
Bin jetzt immoment ein wenig überfragt.
Mfg
-
Für die Datenbank-Abfragen würde ich einen Thread Pool benutzen. Wenn man für jeden Client einen Thread erstellt wird das ein bisschen viel.
-
Wenn ich Red Skall richtig verstanden habe, hat er unrecht. Wenn jetzt zum Beispiel eine lange Datenbankoperation ausgeführt wird, kann während dieser Zeit nichts anderes gemacht werden, auch dein OnReceive wird nicht ausgeführt. Es sei denn du benutzt halt Threads.
-
Verwechselt da mal was nicht.
CAsyncSocket baut auf callbacks auf. Aus diesem Grund sind sie Async. Dh es wird etwas an den Socket übergeben und dann weitergemacht. Man wird dann von Socket beachrichtigt wenn sich was getan hat (Mal alles vereinfacht. Nicht der Socket benachrichtig)
Die eigentliche Dialogklasse ist nur ein Thread.
Will man da was pro Client abarbeiten braucht man Threads die unabhängig von der Dlg-Klasse (DLG-Thread) sind.
-
Wenn ich euch richtig verstehe, muss ich also doch mit Threads arbeiten und jedem Client einen zuordnen. Jeder dieser Threads durchläuft dann alle Funktionen und schließt die Verbindung zwischen Client und Server am Ende oder?
Mfg
-
Wenn man CAsyncSocket benutzt braucht man für den Netzwerkcode keine zusätzlichen Threads!
Für Datenbankabfragen oder andere zeitaufwendige Dinge braucht man aber zusätzliche Threads da sonst alles geblockt wird.
-
Wenn du nur mit ein paar Clients rechnest kannst du der Einfachheit halber für jeden Client einen Thread erstellen und dann z.B. CSocket darin benutzen. Aber wenn dein Server viele Clients erwartet ist das eine sehr schlechte Lösung.
-
Wie ich anfangs schon sagte ich habe mich in diesen Bereich neu eingelesen und diese ist mein erstes Prog mit multitasking.
Deshalb wäre es super wenn du es ein wenig erklären könntest.
Was heisst viele Threads und wie würde die andere Lösung aussehen.
Mfg
-
omg, ich dachte bisher das CAsyncSocket auf threads aufbaut !! danke, das ihr mich eines besseren belehrt habt !!!!! das war wichtig für mich
-
Red Skall
ich habe noch mal eine Frage zu deinem Code.// m_sListenSocket ist objekt von CMySocket if (m_sListenSocket.Accept(*((CMySocket*) oData[m_cConnData.GetSize() -1]))) { }Was ist m_cConnData ,wofür wird es benutzt und wie wird es deklariert.
Ich habe bis jetzt den nachfolgenden Code benutzt und es klappt auch, deswegen habe ich diese Frage nicht sofort gestellt.if (m_sListenSocket.Accept(*((CMySocket*) oData[oData.GetSize() -1]))) { }Aber es interessiert mich schon was der unterschied ist.
Mfg
-
also das beispiel finde ich programmiertechnisch sowieso etwas umständlich. der ist schon etwas älter, jetzt würde ich das so machen:
OnSocket_Accept() { CMySocket *mCurSock = new CMySocket(); m_oData.Add(mCurSock); if (m_sListenSocket.Accept(*mCurSock)) { // weiter machen ... } }da haste dieses gewusel nicht mehr drin

ich bin mir nicht mal mehr ganz sicher was 'm_cConnData' genau war ^^ denke das sollte 'm_oData' gewesen sein o.ä.
EDIT:
aber das mit dem threads würde ich auch gerne noch wissen. habe eben meine anwendung getestet. da kommt auch nichts an, wenn socket eine funktion aufgerufen hat und diese noch nicht abgearbeitet ist. callback halt -.-würde nur gerne wissen wie man die sockets in einem eigenen thread ablaufen lässt. (wahrscheinlich wieder mal einfach als ich mir das vorstelle)
-
Danke klappt auch und sieht viel besser aus.
Wenn ich mich recht erinnere würdest du dann jedem eine ID zuordnen.
Wahrscheinlich im Abschnitt "weiter machen" oder ?OnSocket_Accept() { CMySocket *mCurSock = new CMySocket(); m_oData.Add(mCurSock); if (m_sListenSocket.Accept(*mCurSock)) { // weiter machen ... // Würdest du das dann so machen? static int nCounter; ++nCounter; mCurSock->m_iID = nCounter; // oder wie ? } }
-
- leg dir einfach eine membervariable in deinem dialogfeld an, z.B. int iLastID.
- im contruktor deines dialogfeldes setzt du diese auf 0
jetzt in OnAccept():
// ... // weiter machen ... mCurSock->iID = iLastID ++;jetzt bekommt jeder client ne andere id.
das mit der id ist nur nen vorschlag. das must du selber entscheiden. je nach anwendung würde ich das anders machen. aber irgendetwas, was deinen client eindeutig identifiziert solltest du drin haben.
@Unix-Tom: kannste mal nen beispiel posten wie das mit den threads aussieht? thx
-
Wofür noch eine ID? Den Socket Descriptor kann man doch zur Identifikation benutzen.