Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Socket Server ohne Threads
Gehe zu Seite 1, 2, 3  Weiter
 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 06.12.2012, 10:41    Titel: Socket Server ohne Threads Antworten mit Zitat

Ich suche noch immer händeringend einen Socket Server, der ohne Threads arbeitet.
TSNE kann ich leider nicht nutzen, da ich mit global shared Variablen arbeiten muss und ich die Verwaltung dieser Variablen mit TSNE einfach nicht gebacken bekomme.

Nun habe ich im englischen Forum diesen Code gefunden:
Code:

    #include "network.bi"
    #include "fbgfx.bi"

    #DEFINE SERVER_PORT 27015
    #DEFINE CLIENT_IP "127.0.0.1"

    '--- SERVER ---

    dim as SOCKET socketId
    dim as sockaddr_in clientAddr
    dim as sockaddr_in serverAddr
    dim as integer serverAddrSize = sizeof(serverAddr)
    dim as integer clientAddrSize = sizeof(clientAddr)
    dim as integer iResult, quit, sendData, sendCount
    dim as string key

    dim as net_data netDataIn
    dim as net_data netDataOut

    dim as fd_set readfds, readfds0
    dim as fd_set writefds, writefds0
    dim as timeval timeout

    iResult = init_socket_API()
    if (iResult <> 0) then
      print "Winsock init: Error"
      sleep
      end
    end if

    socketId = socket_(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
    if (socketId < 0) then
      print "Socket: Error"
      close_socket_API()
      end
    end if

    serverAddr.sin_family = AF_INET
    serverAddr.sin_port = htons(SERVER_PORT)
    serverAddr.sin_addr.s_addr = htonl(INADDR_ANY)

    iResult = bind(socketId, cptr(sockaddr ptr, @serverAddr), serverAddrSize)
    if (iResult < 0) then
      print "Bind: Error"
      close_socket_API()
      sleep
      end
    end if

    clientAddr.sin_family = AF_INET
    clientAddr.sin_port = htons(SERVER_PORT)
    clientAddr.sin_addr.s_addr = inet_addr(CLIENT_IP)

    FD_ZERO(@readfds0)
    FD_ZERO(@writefds0)
    FD_SET_(socketId, @readfds0)
    FD_SET_(SocketId, @writefds0)

    print "q = quit"
    print "s = send"

    while (quit = 0)
     
      quit = 0: sendData = 0
      key = lcase(inkey())
      if (key = "q") then quit = 1
      if (key = "s") then sendData = 1

    'Keep a backup because SelectSocket will change the data
      readfds = readfds0
      writefds = writefds0
      timeout = type(0, 0)

      iResult = selectSocket(FD_SETSIZE, @readfds, @writefds, NULL, @timeout)
      if (iResult = 0) then
        print "SelectSocket: Timeout"
      elseif (iResult < 0) then
        print "SelectSocket: Error"
      else
        'print "SelectSocket: Sockets ready: "; iResult
      end if
     
      if(sendData = 1) then
        netDataOut.seqNr = sendCount
        netDataOut.text = "Server says: No!"
        if(FD_ISSET(socketId, @writefds)) then
          print "Send: Trying..."
          iResult = sendto(socketId, cptr(ubyte ptr, @netDataOut), _
            sizeof(net_data), 0, cptr(sockaddr ptr, @clientAddr), clientAddrSize)
          if (iResult < 0) then
            print "Send: Error"
            closeSocket(socketId)
            close_socket_API()
            sleep
            end
          else
            print "Bytes send:"; iResult;
            print " to: "; inet_addr_rev(clientAddr.sin_addr)
          end if
        end if
        sendCount += 1
      end if
     
      if(FD_ISSET(socketId, @readfds)) then
        print "Receive: Trying..."
        iResult = recvfrom(socketId, cptr(ubyte ptr, @netDataIn), _
          sizeof(net_data), 0, cptr(sockaddr ptr, @clientAddr), @clientAddrSize)
        if (iResult > 0) then
          print "Bytes received:"; iResult;
          print " from: "; inet_addr_rev(clientAddr.sin_addr)
          print "SeqNr: "; netDataIn.seqNr;
          print " text: "; netDataIn.text
        elseif (iResult = 0) then
          print "Receive: Connection closed"
          closesocket(socketId)
          close_socket_API()
          sleep
          end
        else
          print "Receive: Error"
          closesocket(socketId)
          close_socket_API()
          sleep
          end
        end if
      end if
     
      sleep 1, 1
     
    wend

    iResult = closesocket(socketId)
    if (iResult < 0) then
      print "CloseSocket: Error"
    end if
    close_socket_API()

    print "End."
    sleep


Arbeitet dieser Code ohne Threads? So ganz verstehe ich den Code leider nicht. Für jede Erklärungshilfe wäre ich dankbar.
Ansonsten wäre ich auch dankbar für einen Beispielcode, der mit WSAAsyncselect und/oder WSAEventselect arbeiten würde.
Vielen Dank
Stevie
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
darkinsanity
aka sts


Anmeldungsdatum: 01.11.2006
Beiträge: 456

BeitragVerfasst am: 06.12.2012, 21:19    Titel: Antworten mit Zitat

Ja, er arbeitet ohne Threads, da ja nirgendwo einer erstellt wird. Allerdings ist das direkte Benutzen der Socket-APIs meiner Meinung nach eine ziemlich hässliche Sache.
Du erstellst hier einen UDP-Socket und wartest bis er bereit ist. Wenn du "s" drückst, sendet er etwas (in diesem Falle wohl an 127.0.0.1), wenn er erkennt, dass es Daten gibt, die er abholen kann, empfängt er sie. Danach wartet er kurz per sleep und fragt dann wieder (per select) ob der Socket bereit ist.
UDP ist allerdings Verbindungslos, daher bin ich mir nicht ganz sicher ob dieses Protokoll auch wirklich benutzen willst.
stevie1401 hat Folgendes geschrieben:
Ich suche noch immer händeringend einen Socket Server, der ohne Threads arbeitet.
TSNE kann ich leider nicht nutzen, da ich mit global shared Variablen arbeiten muss und ich die Verwaltung dieser Variablen mit TSNE einfach nicht gebacken bekomme.

Was genau ist denn dein Problem? Im Prinzip musst du nur dafür sorgen dass deine Variablen entsprechend initialisiert sind und du sie vor gleichzeitigem Zugriff schützt (z.B. per Mutex). Die API von TSNE ist deutlich schöner als das direkte Socket-Interface und du kannst deutlich weniger falsch machen.
_________________
Traue keinem Computer, den du nicht aus dem Fenster werfen kannst -- Steve Wozniak
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 07.12.2012, 16:04    Titel: Antworten mit Zitat

Erst einmal vielen Dank für deine Antwort.
Bei meinem Programm handelt es sich um einen Doppelkopf-Server.
Allein schon die Tatsache, dass der Server allen Spielern am Tisch die Karten auf dem Tisch anzeigen soll,
wenn jemand eine Karte geschmissen hat,macht TSNE sinnlos, denn er muss demuxen oder muxen was das Zeug hält.
Da kann ich gleich einen threadlosen Server bauen. Ich habe es mehrfach mit TSNE probiert, aber es funktioniert einfach nicht und ist eine irre Arbeit.
Von einfach kann da keine Rede sein, leider.
Zur Zeit arbeite ich mit WSAAsyncselect, was teilweise recht gut funktioniert, aber natürlich auch Nachteile hat. Zum Beispiel, dass ich ein Fenster brauche.
Deshalb fällt leider auch ein vServer aus und ich muss den Server über einen meiner Rechner laufen lassen.
Deshalb wäre ich über einen Beispielcode mit WSAeventselect sehr dankbar.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 07.12.2012, 16:44    Titel: Antworten mit Zitat

Naja.... @ stevie ... eigentlich ist das Problem eher, das du den server komplett umschreiben müsstest. Du weist ja, da sind viele Strukturelle Probleme vorhanden. an TSNE liegt das in dem Falle nicht.

Und, wild muxen muss man da auch nicht, wenn der source entsprechend geschrieben ist.
Andernfalls natürlich schon. Aber, das ist ja beim umbauen von einem zum anderem immer recht problematisch.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 07.12.2012, 18:29    Titel: Antworten mit Zitat

Die "strukturellen Probleme" sind die shared Variablen, wenn ich TSNE verwenden will. Aber nur dann.
Ich weiß beim besten Willen nicht wie ich die NICHT benutzen sollte, denn irgendwie müssen die Spielernamen, Tische etc. gehandelt werden.
Dies kann m.E. nur global gemacht werden. Dies wäre auch beim schreiben in eine Datenbank nicht anders. Auch dort würde es sofort E/A Fehler geben,
sobald mehrere Clients darin lesen wollen.
Ich wüßte also nicht einmal im Ansatz wie ich einen Server schreiben kann, der Daten on the fly bearbeitet und verwalten muß, damit er mit TSNE funktioniert.
Aber vielleicht kannst du mir ja mal einen Tip geben.
Vielen Dank.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 07.12.2012, 18:34    Titel: Antworten mit Zitat

Prinzipiel kannst du dich an dem hier orientieren. Ist zwar ein HTTP Server, nutzt aber die selben mechanissmen.

http://www.freebasic-portal.de/porticula/test-serverbas-740.html

fast ganz unten findest du ein

Code:
    Case "/status"                                  'Der CLient will einen Status haben
        T += "<html>"                             'Es wir deien HTML-Seite erzeugt
        T += " <head>"
        T += "  <title>Test-Server</title>"         'Mit eine Titel
        T += " </head>"
        T += " <body>"
        T += "  <p>= Mein Status =</p>"             'Und einem sichtbarem Text
        MutexLock(ClientMutex)                      'Wir müssen das MUTEX sperren, weil wir auf daten im Array zugreifen
        T += "  <p>Ich habe / hatte maximal " & ClientC & " Verbindungen gleichzeitig</p>"
        T += "  <p>Deine IP-Adresse: " & ClientD(CIndex).V_IPA & "</p>"
        T += "  <p><a href=""block"">Blockiere meine IP-Adresse</a></p>"
        MutexUnLock(ClientMutex)                    'Danach können wir die Sperre wieder aufheben
        T += " </body>"
        T += "</html>"                                'Es wir deien HTML-Seite erzeugt


Dort ist zu erkennen, das beim zugriff auf globale variablen eine mutexsterre erfolgt.


Aber, wie schon geschrieben, empfehle ich dir hier dringend, das gesammtkonzept neu zu gestalten. Die vorgehensweise und der code-aufbau ist schon recht verworren, um das ganze effizient zu halten.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 07.12.2012, 19:03    Titel: Antworten mit Zitat

Vielen Dank!
Kann ich in das
MutexLock(ClientMutex)

MutexUnLock(ClientMutex)
jetzt die Nachricht von den Clients reinpacken und in einer sub bearbeiten?

Wie oben schon geschrieben, ich wüßte nicht einmal im Ansatz, wie ich das ohne shared Variablen machen könnte.
Und - das möchte ich auch erwähnen - das Konzept ist eigentlich sehr gut durchdacht.
Es mag als Nicht-GFA-Progger etwas verwirrend sein, es ist tatsächlich aber sehr logisch aufgebaut und GFA-Progger können den Code sehr gut und sehr leicht nachvollziehen.
Es funktioniert ja auch als Netzwerkserver mit WSAAsyncselect, aber genau das möchte ich ja am liebsten umgehen.

Noch etwas anderes:
Wenn bei jeder Clientnachricht ein

MutexLock(ClientMutex)
GehInSubBearbeiteDaten
MutexUnLock(ClientMutex)

erfolgen muss, welchen Sinn machen dann die Threads noch? Ich stelle sie ja bei jedem Durchgang aus oder verstehe ich da was falsch?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 08.12.2012, 01:55    Titel: Antworten mit Zitat

Hatest du mal die Links von mir durchgelesen, die ich dir in der PM geschickt hatte? .. bezüglich Threads udn Mutexe? .. dort ist eigentlich beschrieben, wie man mit soetwas umgeht, und wo die probleme dabei sind.

Das MutexLock() / Unlock solltest du nur um die elemente legen, die shared sind.


beispiel:

Code:

dim shared bla as uinteger

sub foo()
dim abc1 as uinteger
dim abc2 as uinteger
dim abc3 as uinteger
mutexlock(...) 'bla ist eine shared. daher muss der zugriff via mutex gesperrt werden
abc1 = bla
mutexUnlock(...) 'danach kann das wieder freigegeben werden
abc2 = abc1 * 2
mutexlock(...) 'hier folgt wieder ein zugriff auf die shared. daher wieder locken
abc3 = abc2 + bla
mutexUnlock(...)
end sub

foo()
end 0


wie zu erkennen, wird die sperre nur dann benötigt, wenn ein zugriff auf die shared von nöten ist. andernfalls nicht.

nochmal, hier kannst du dich bezüglich dieser themen informieren:
threading: http://www.freebasic-portal.de/tutorials/threading-56.html ... probleme und handling von threads incl mutex-schutz

mutex: http://www.freebasic-portal.de/tutorials/mutexe-54.html ... was mutexe machen.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 08.12.2012, 09:07    Titel: Antworten mit Zitat

Du ahnst gar nicht wieviele Stunden und Tage ich mich schon mit TSNE beschäftigt habe.
Natürlich habe ich schon alle deine Beispiele mehrfach durchgekaut.
Genau deshalb bin ich ja zu dem Ergebnis gekommen, dass TSNE nicht anwendbar ist, zumindest nicht für mich.
Ich verstehe den Code nicht und er ist für mich nicht nachvollziehbar.
Ich weiss nicht wann ich mutexlock und mutexunlock anwenden kann oder wie.
Die einzige Chance für mich würde ich sehen, wenn ich mutexlock machen könnte, dann die Nachrichten vom Client verarbeiten könnte und dann wieder mutexunlock machen könnte.
Ich habe nun mehrfach gefragt ob bzw. wie das gehen könnte, habe diesbezüglich aber keine Antwort erhalten.
Probiert habe ich vieles, funktioniert hat nichts.
Das Problem ist doch folgendes:
Die Nachricht vom Client kommt rein.
Nun müssen Serverseitig zwangsläufug ganz viele Routinen durchlaufen werden, die dim shared Variablen beinhalten, um zu gucken, welcher Spieler an welchem Tisch welche Karte geworfen hat.
Der Server müßte also nach Erhalt der Clientnachricht ein mutexlock machen, die Daten verarbeiten und dann wieder ein mutexunlock.
Dies funktioniert aber überhaupt nicht, denn der Server hängt sich immer auf.
Also frage ich letztmalig (dann gebe ich es echt auf hier):
Wie kann ich die Nachricht vom Client KOMPLETT mutexgesperrt verarbeiten?

Inzwischen habe ich für mich ja eigentlich ja auch schon TSNE abgehakt und würde mich über ein Beispiel mit Freebasic mit WSA Asyncselect oder WSAeventselect freuen.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4704
Wohnort: ~/

BeitragVerfasst am: 08.12.2012, 13:18    Titel: Antworten mit Zitat

Wenn sich der Server aufhängt, lockst du vermutlich falsch - zwei MUTEXLOCK ohne MUTEXUNLOCK oder etwas in der Art.

Die Spieler werfen doch nicht gleichzeitig ihre Karten? Von der Theorie her würde ich das so angehen: Der Server teilt Spieler X mit, dass er am Zug ist und wartet auf Rückmeldung. Sobald er die bekommt, schickt er an alle Spieler den aktuellen Spielstand und dann dem nächsten Spieler die Information, dass er an der Reihe ist. Nur die ausgetauschten Nachrichten muss tatsächlich gekapselt werden; die Nachricht kann dann auch (mutexgeschützt) in eine lokale Variable übertragen werden, auf die du (ohne MUTEXLOCK) problemlos weiter zugreifen kannst.

ThePuppetMaster hat ein paar Sachen als Tutorial ins Portal gestellt; ansonsten kannst du auch mal in mein Buch schauen, da gehe ich auch knapp auf die Thematik ein (interessant wohl vor allem Kapitel 8 ).
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.


Zuletzt bearbeitet von nemored am 08.12.2012, 13:27, insgesamt 2-mal bearbeitet
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 08.12.2012, 13:27    Titel: Antworten mit Zitat

@nemored

idee ist nicht schlecht, aber nicht schön machbar, denn es gibt ja noch n haufen anderer Dinge, die asynchron gehandelt werden sollten.

z.B. Das Senden von Nachrichten (Chat), neue Spieler, spieler die den raum verlassen, spielen die einen raum wechseln, spieler die den server verlassen, usw.

wenn jemand am ziehen ist, udn derjenige hat sagen wir mal max. 15sec dafür, dann müssen all diese anderen nachrichten min. 15sec warten. will also jemand einen anderen raum betreten und klickt auf "join", dann muss er "kurioser weise" erstmal (im schelchtestem falle) 15sec warten, bis er eine rückmeldung vom server für diese operation erhält.

Daher sollte ja sowas (vorallem bei server) asynchron gemacht werden.

Wie man das aber macht, bleibt natürlich jedem selbst überlassen.

@stevie1401

prinzipiel kannst du auch so vorgehen. Wenn du nicht expliziet die optimierung verwenden willst, das der zugriff auf zu schützende resourcen (shared vars) effektiv wird, dann kannst du regulär ganz normal die verarbeitungsroutine für die daten per mutexlock() und Unlock() einklammern.

so wie von dir beschrieben.
Code:
MutexLock(ClientMutex)
GehInSubBearbeiteDaten
MutexUnLock(ClientMutex)


das macht zwar den sinn hinter "asynchron" kaput, aber funktionieren tut es.

Wichtig ist nur, das du in den locked bereichen keine "wartenden" dinge tust. Das kann dann zu probleme führen, wie ein hängen, Auch rekrusive aufrufe führen dazu (welche schwer zu lokalisieren sind).

die "verarbeiten" routine sollte so schnell wie möglich die daten verarbeiten. Ohne wartezeit! dann funzt es regulär problemlos.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4704
Wohnort: ~/

BeitragVerfasst am: 08.12.2012, 13:40    Titel: Antworten mit Zitat

Das mit der asynchronen Verarbeitung ist schon richtig; das ist aber dann doch nur ein begrenzter Befehlsbereich, der da abgearbeitet werden muss. So viele verschiedene Einzelnachrichten, auf die ich da reagieren muss, kommen da gar nicht zusammen (zumal TSNE ja für das joinen gleich noch eine extra Prozedur aufruft, wenn ich mich nicht irre). Kommt natürlich auch auf das Spiel an - bei einem Kartenspiel macht es in der Regel nicht viel Sinn, während des Spiels beizutreten, es sei denn du bist rausgeflogen und musst dich wiederverbinden.

Was ich letztendlich damit sagen will: Grundlage für einen reibungslosen Ablauf ist ein gutes Netzwerkprotokoll. grinsen
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 08.12.2012, 13:43    Titel: Antworten mit Zitat

jo. ein gutes protokoll ist natürlich ein wichtiger faktor.

bezüglich join und tsne.
naja... tsne erzeugt pro verbindung zwischen server und client einen eigenen thread.
10 verbindungen = 10 threads.

Worauf ich beim "join" hinaus wollte ist eher in richtung "bewegung auf dem server".
Wenn man die verbindugn zum server etabliert hat, erhält man z.B. eine liste mit möglichen räumen, welche man betreten kann. udn das gäbe bei "wartebefehle" in der datenverarbeitungs-routine probleme bezüglich dem timing.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 08.12.2012, 13:55    Titel: Antworten mit Zitat

Erst mal vielen Dank für eure Mühen zwinkern
Und genau, Puppetmaster, so einfach ist das alles leider nicht.
Anhand der ClientNachricht agiert der Server.
Wirft ein Spieler eine Karte, so teilt der Server dies nur den Spielern an seinem Tisch mit.
Verlässt ein Spieler einen Tisch, so teilt er dies allen Spielern mit, da diese wissen müssen, dass ein Platz an einem Tisch freigeworden ist.
Das Chatten ist noch komplizierter: Man kann am Tisch chatten, in der Lobby (ein anderer Raum), man kann "flüstern", also nur an eine gezielte Person etwas schreiben oder man kann an alle Spieler etwas schreiben.
Es gibt also viele Sendeoptionen - und genau da ist, glaube ich, der Hund begraben.
Per WSAAsyncselect klappts ja (auch wenn der Server manchmal einen Spieler einfach rausschmeisst, aber der kann sich einfach wieder anmelden und weiterspielen),
mit dem
MutexLock(ClientMutex)
GehInSubBearbeiteDaten
MutexUnLock(ClientMutex)
klappt es leider nicht.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 08.12.2012, 13:59    Titel: Antworten mit Zitat

das der server einen raus schmeist, kann z.B. einfach daran liegen, weil "wartende routinen" in der verarbeitung vorhanden sind. dadurch kommt es zu "lags" wärend der kommunikation in folge davon zu einem timeout, wodurch der server / client die verbindung trennt.

wenn du mir mal das kommunikations-protokoll zukommen lannen kannst, schaue ich mal, ob ich das per tsne realisiert bekomme.


MfG
TPM
_________________
[ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ]
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
nemored



Anmeldungsdatum: 22.02.2007
Beiträge: 4704
Wohnort: ~/

BeitragVerfasst am: 08.12.2012, 14:04    Titel: Antworten mit Zitat

Der Vorteil beim Chat ist, dass die Abarbeitung nicht übermäßig zeitkritisch ist. Bei einem Spiel wäre es schon ärgerlich, wenn derjenige, der als erstes reagiert, dann erst als letzter abgearbeitet wird. Wenn meine Chat-Nachricht eine viertel Sekunde zu spät abgearbeitet wird, ist mir (persönlich) das relativ egal.

Wie gesagt, einfacher ist das System
Code:
DIM AS nachrichtentyp meineLokaleNachricht
MUTEXLOCK meinMutex
meineLokaleNachricht = aktuelleGlobaleNachrichtenvariable
MUTEXUNLOCK meinMutex
SELECT CASE meineLokaleNachricht
' ...
END SELECT


Stark vereinfacht, aber so hast du so wenig gelockt wie möglich.
_________________
Deine Chance beträgt 1:1000. Also musst du folgendes tun: Vergiss die 1000 und konzentriere dich auf die 1.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
RWK



Anmeldungsdatum: 04.07.2011
Beiträge: 44

BeitragVerfasst am: 08.12.2012, 16:11    Titel: Antworten mit Zitat

Stevie,

ich glaube nicht das das so schwer wäre mit TSNE.

Ich für meinen Teil benutze bei meinem Laufzeiterfassungsprogramm das TSNEPlay...und das wäre sicherlich auch für Dich geeignet.

Und bei Zieleinläufen treten dort sicherlich mehr Aktionen am Server auf als bei ein paar Doppelkopfrunden würde ich jetzt mal frech behaupten.

Bei mir sind des..
1 x Teilnehmererfassung die die sich anmeldenden Läufer eingibt (auch während andere Läufe laufen)
2 x Zeitnehmer die ein Signal senden wenn jemand über die Ziellinie läuft
1 x Platzierungsnehmer der gleichzeitig die Startnummern gemäß der Einlauffolge erfasst.
1 x Moderator der ständig Startnummer abfragt, damit er Name, Verein, Altersklasse etc vom Server bekommt. und er bekommt immer die Einlaufzeiten und dann den Einläufer übermittelt damit er ein vorläufiges Ergebnis hat.
1 x ein Auswerter, der die Zieleinläufe kontrolliert und ein endgültiges Ergebnis erstellt.

und das ganze wird auch gleichzeitig noch in einer SQLite Datenbank weggeschrieben.

und noch dazu ist das bei mir alles andere als sauber gecodet, weil mir einfach die Zeit fehlt das ordentlich zu bauen...
trotzdem...
das alles wickelt der Server ab und hat noch Langeweile. So wird es auch in deinem Fall sein, wenn nicht 1000 Leute gleichzeitig spielen.

Der Server macht nix anderes als :

Code:
Sub TSNEPlay_Message(ByVal V_FromPlayerID As UInteger, ByVal V_ToPlayerID As UInteger, ByVal V_Message As String, ByVal V_MessageType As TSNEPlay_MessageType_Enum)
    Dim As String text = "[NACH]   Von PlayerID:" & V_FromPlayerID & "   Fuer PlayerID:" & V_ToPlayerID & "   Type:"
    text = text & "   Nachricht:>" & V_Message & "<"   
    Console (text)
    Select Case V_MessageType
        Case TSNEPlay_MSGType_Regular
            checkMessage(V_FromPlayerID, V_Message)
        Case TSNEPlay_MSGType_Private           
        Case TSNEPlay_MSGType_Notice           
            AddMessage (V_FromPlayerID, V_Message)
        Case TSNEPlay_MSGType_Hightlighted       
        Case Else                               
    End Select

End Sub


Code:
Sub checkMessage(ByVal User As UInteger, ByVal Message As String)
    Dim As String xText, a, b
    Dim As Integer x,y
   
    Select Case (Left(Message,8))
        Case "GogoLauf"
            StartLauf
        Case "Get_Time"
            xText = "Set_Time:" & aktTime
            xText += ";" & aktLauf.lStatus
            xText += ";" & aktLauf.lName
            xText += ";" & aktLauf.lStarter           
            xText += ";" & aktLauf.lZusatz1
            xText += ";" & aktLauf.lZusatz2
            TSNEPlay_SendMSG(User, xText )       
        Case "Get_Teil"
            xText = Mid(Message,10)
            Do
              If xtext = teilnehmerdb(x,0) Then
                xText = "Get_Teil:" & teilnehmerDB(x,2) & " " & teilnehmerDB(x,1) & Chr(13) & Chr(10) & TeilnehmerDB(x,3) & " -- " & teilnehmerDB(x,9)
                Exit Do
              End If
            x = x + 1
            Loop Until teilnehmerdb(x,0) = ""
            If Left(xText,1) <> "G" Then
                xText = "Get_Teil:" & "Nummer nicht gefunden!"
            End If
            TSNEPlay_SendMSG(User, xText)
         Case "Set_Teil"
            xText = Mid(Message,10)
            If xText = "ALLE" Then
                SendeAlleTeilnehmer (user)
                Exit Sub
            End If
            UpdateTeilnehmer(xText)
         Case "Set_Lauf"
            xText = Mid(Message,10)
            If xText = "ALLE" Then
                SendeAlleLauf(user)
            End If           
         Case "In_Zeit1"
             xText = Mid(Message,9)
            IncomingZeit1(xText)
         Case "In_Zeit2"
             xText = Mid(Message,9)
             IncomingZeit2(xText)         
         Case "In_Platz"
             xText = Mid(Message,9)       
             IncomingPlatz(xText)
    ...
    End Select
End Sub


Private Mitteilung könnte ich auch einbauen...habe ich aber keinen Bedarf für.

Und ein
Code:
TSNEPlay_SendMSG(0, xText )

sendet z.B. die Nachricht immer an alle Clients ... z.B. für die Zu- und Abgänge in der Userliste.
Oder auch für den Kartenzug...wenn den nämlich alle Clients mitgeteilt bekommen, könnte der schauen, ob das sein Spiel betrifft. wenn nicht halt verwerfen den Kartenzug...-> das würde auch gleichzeitig die Möglichkeit eröffnen sowas wie Beobachter eines Spiels einbauen zu können.

Wie dem auch sei. Ich glaube nicht das das so schwer umzusetzen wäre. Das schwieriger scheint mir ehr zu sein, das Du dich innerlich umstellen musst.
Ich kenne das von mir.... ich hatte immer noch (oder habe vielleicht auch noch teilweise) VB 6 im Hinterkopf...da konnte man alles mögliche quasi im Schlaf realisieren..(wenn es denn nicht zügig laufen solll lächeln )

Grüße
Rainer
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 08.12.2012, 16:41    Titel: Antworten mit Zitat

Hallo Rainer,
vielen Dank für deine Hilfe.
Ich bin nun etwas verblüfft.
Ich darf in der checkMessage() mit Dim Shared Variablen arbeiten???
Denn genau darum geht es ja. Es wird geprüft, was gerade anfällt.
Verläßt z.B. Spieler "Stevie" einen Tisch wird folgendes geprüft:
For i=1 to TischAnz 'TischAnz ist eine DimShared Integervariable
For j=1 to 4
If TischSpieler(i,j)="Stevie" then 'TischSpieler() ist ein Dim Shared String
TischSpieler(i,j)="frei"
TischNr=i
End If
Next j
Next i
If TischNr>0 then
sendeAnAlleSpielerVonTisch(TischNr,"Stevie hat den Tisch verlassen")
End if


Das war jetzt nur mal ein Beispiel.
DAS darf ich also problemlos in der sub checkmessage schreiben ohne
MUTEXLOCK
MUTEXUnLOCK
machen zu müssen? Wieso das denn plötzlich???
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
RWK



Anmeldungsdatum: 04.07.2011
Beiträge: 44

BeitragVerfasst am: 08.12.2012, 16:55    Titel: Antworten mit Zitat

Code:
        Case "Get_Teil"
            xText = Mid(Message,10)
            Do
              If xtext = teilnehmerdb(x,0) Then
                xText = "Get_Teil:" & teilnehmerDB(x,2) & " " & teilnehmerDB(x,1) & Chr(13) & Chr(10) & TeilnehmerDB(x,3) & " -- " & teilnehmerDB(x,9)
                Exit Do
              End If
            x = x + 1
            Loop Until teilnehmerdb(x,0) = ""
            If Left(xText,1) <> "G" Then
                xText = "Get_Teil:" & "Nummer nicht gefunden!"
            End If
            TSNEPlay_SendMSG(User, xText)


Ist ja nichts anderes als hier.... der Moderator fragt nach Teilnehmernummer z.B. 517...
ich guck in der Datenbank nach der Nummer...wenn gefunden baue ich einen String zusammen und schicke den an den Moderator (User) zurück.

live getestet ist das bis jetzt nur bei so ca. 600 Teilnehmern...keine Probleme.

Das klappt deswegen, weil ich mich nicht mehr in der CallBackroutine von TSNE befinde. Darum auch mein Umweg aus der TSNEPlay_Message Sub..die ja das Callback von TSNE bei Dateneingang ist....einfach die Nachricht an eine eigene Sub weiterzuleiten.

Das ganze in der CallBack Routine verarbeitet crasht das Programm.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
stevie1401



Anmeldungsdatum: 04.07.2006
Beiträge: 133

BeitragVerfasst am: 08.12.2012, 19:37    Titel: Antworten mit Zitat

Okay, das teste ich mal, das wäre ja echt der Hit^^
Vielen Dank lächeln
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Gehe zu Seite 1, 2, 3  Weiter
Seite 1 von 3

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz