Server mit mehreren Puffer für ReceiveNetworkData() ?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
captain third
Beiträge: 194
Registriert: 12.12.2004 13:14
Kontaktdaten:

Server mit mehreren Puffer für ReceiveNetworkData() ?

Beitrag von captain third »

hi,

ich hab mal überlegt,wenn man einen server hat,mit einem puffer für ReceiveNetworkData() ,und ungefähr 10 oder 20 Clienten beim server connectet haben und die ganze zeit senden und empfangen,wäre es für den server eine große arbeit und die clienten empfangen alle etwas später als normal,wäre es sinnvoll den server mit mehreren puffern zu machen?

wenn ja,wie funktioniert das?ich hab mir überlegt,das erstmal kontroliert wird ob der oder der puffer voll ist und dann einen anderen puffer benutzt zum empfangen,während die anderen grade geleert werden.wäre das sinvoll?
natoll,jetzt muss ich noch einen Rechner zusammenbaun der 24 stunden am Tag online ist und meinen Server für mein Projekt Order of Blance laufen lässt
netfreak
Beiträge: 91
Registriert: 23.10.2004 18:30
Kontaktdaten:

Beitrag von netfreak »

Ich denke nicht zu mindeste wenn du ein Chat Server machst den das was der Server empfängt muss ja meist an die Clients weiter gesendet werden!


mfg
netfreak
mfg
netfreak
Benutzeravatar
captain third
Beiträge: 194
Registriert: 12.12.2004 13:14
Kontaktdaten:

Beitrag von captain third »

ne ich meine jetzt fürn onlinespiel...
natoll,jetzt muss ich noch einen Rechner zusammenbaun der 24 stunden am Tag online ist und meinen Server für mein Projekt Order of Blance laufen lässt
netfreak
Beiträge: 91
Registriert: 23.10.2004 18:30
Kontaktdaten:

Beitrag von netfreak »

mmh da ist es ja was anderes da könntest du mit Zwei Buffern arbeiten! Aber ob das was bringt weiß ich net.
mfg
netfreak
Benutzeravatar
Lars
Beiträge: 347
Registriert: 31.08.2004 23:53
Wohnort: Shanghai
Kontaktdaten:

Beitrag von Lars »

Mit ungefähr 10 bis 20 Clienten solltest du mit ungefähr 10 bis 20 Buffern
arbeiten.

Eigentlich solltest du beim Connecten eines Clients direkt eine ClientListe
anlegen (LinkedList), die dann die Struktur [c]ClientID, u.U. IP etc,
*ReceiveBuffer, BytesInReceiveBuffer[/c] hat.

Wenn jetzt ein Client etwas sendet, dann guckst du erst, welche ID das
ist, schlägst dann in der Liste den passenden Buffer nach und empfängst
in den richtigen Buffer.

Mehrere Buffer zum Senden sind aber absolut sinnlos, da du eh immer nur
ein SendNetworkData() gleichzeitig haben kannst, d.h. da reicht einer.


Bevor jetzt die Zweifel kommen, warum ich diese Methode vorschlage:
Mit anderen Methoden weißt du nie, welche Daten von welchem Clienten
stammen, reines Chaos ist nicht nur vorprogrammiert sondern eine
gerechte Bestrafung :wink:

Wichtig ist allerdings, dass du bei der Größe eines Standard Clientbuffers
aufpasst, da du von diesen Buffern u.U. mal 50 auf einmal haben musst,
wie viele genau hängt von deiner Anwendung ab. D.h. du musst genau
abwägen, wie lang der längste Command ist und den Buffer möglichst
klein halten.
Lars
The only problem with troubleshooting is, that sometimes the trouble shoots back.
P4 2,6Ghz, 512MB RAM, GeForce 6200, WinXP Pro SP2, PB V3.94
Benutzeravatar
captain third
Beiträge: 194
Registriert: 12.12.2004 13:14
Kontaktdaten:

Beitrag von captain third »

mmmh,jeder Client bekommt sein eigenen Puffer,das gefällt mir,hört sich gut an,und theoretischer weise müsste es auch die bessere lösung sein,aber dazu muss ich nochmal die hilfe studieren(für die zukunft:Ich glaube ichwerd wahrscheinlich öfters mal nachfragen,seit bitte nicht genervt)

jedenfalls,danke für die antwort

[Edit]
Oh Gott,die hilfe ist zu unverständlich,ich habe das eine tut bei purearea runtergeladen,"prozeduren uns struckturen",dadurch bin ich ein bissl schlauer geworden,kennt jemand noch weitere tutorials? bei purearea hab ich keine weiteren gefunden
natoll,jetzt muss ich noch einen Rechner zusammenbaun der 24 stunden am Tag online ist und meinen Server für mein Projekt Order of Blance laufen lässt
Benutzeravatar
captain third
Beiträge: 194
Registriert: 12.12.2004 13:14
Kontaktdaten:

Beitrag von captain third »

ich hab mich jetzt der hilfe nach orientiert und hab auch gleich einen schnipsel geschrieben den ich dann beim server rein mache,der schnipsel sieht jetzt so aus

Code: Alles auswählen

Structure Puffer
  Puffergröße.w
EndStructure

Dim Client.Puffer(1000)

Sevent=NetworkServerEvent()

Select Sevent
  Case 1
    Addelement ClientID())
    ClientID=NetworkClientID()
    Client(ClientID)\Puffergröße=500
    
  Case 2
ich hab jetzt nur keine ahnung was ich bei case 2 reinschreiben soll...weil irgendwie muss ja dann der bestimmte puffer vom ClientID genommen werden,könnt ihr mir helfen?
natoll,jetzt muss ich noch einen Rechner zusammenbaun der 24 stunden am Tag online ist und meinen Server für mein Projekt Order of Blance laufen lässt
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

es gibt natürlich auch eine 2. Möglichkeit die ich interessanter finde. Du brauchst nur 2 Buffer. Ein für das Senden und ein für das Empfangen. Den Client übergibst du beim Connecten vom Client eine GUID (wie du die erstellst ist mir egal, hauptsache sie ist etwas einmaliges). Diese GUID sendet der Client dann immer mit. Paketstruktur könnte etwa so aussehen:

Code: Alles auswählen

<Befehl>[Byte 3]<Paketlänge>[Byte 3]<Client GUID>[Byte 2]<Base64Data>[Byte 4]
Das ist schon was. Den Befehl machste halt numeric und Paketlänge ist klar. So geht nicht nur nichts verloren sondern man sparrt Speicher für andere Programme. Hier mal ein kleiner Code um Daten zu empfangen:

Code: Alles auswählen

    ReceiveNetworkData(ClientID, *ReceiveBuffer, #BufferLen) 
    SplitNetPacket(PeekS(*ReceiveBuffer, #BufferLen))
    ForEach PaketPool(): ParseNetPacketServer(@PaketPool(), ClientID): Next 
    ClearList(PaketPool())                            
    RtlFillMemory_(*ReceiveBuffer, #BufferLen+1, 0)
das Ab arbeiten des Paketpools kannste natürlich auch in einen anderen Thread auslagern. Dann ist der Server noch etwas schneller. Weil ich heut mein guten Tag hab, hier auch noch die Structur der Pakete:

Code: Alles auswählen

Structure sNetPacket                    ;/ Netzwerkpaket
    pakBefehl.l                         ; Befehl in Zahl
    pakLaenge.l                         ; Länge des Paketes
    pakClientID.s                       ; ClientID von wem das Paket stammte
    pakSucceed.b                        ; Angabe ob das Paket gültig ist
    pakGUID.s                           ; GUID des Paketes. Identifikation des Clients. 
    pakData.s                           ; Daten die das Paket enthält. 
EndStructure
Bild
Benutzeravatar
captain third
Beiträge: 194
Registriert: 12.12.2004 13:14
Kontaktdaten:

Beitrag von captain third »

mmmh,da stimmt was nicht,da ich selber nicht mehr durchblicke zeig ich euch mal den code

Code: Alles auswählen

NewList ClientID()

OpenConsole()
init=InitNetwork()
If init=0
 PrintN("Netzwerk nicht initialisiert")
EndIf
CreateServer=CreateNetworkServer(500)
If CreateServer=0
 Print("Kein Server aufgemacht")
Else
 ConsoleLocate(30,0)
 Print("Server offen")
EndIf

Structure sNetPacket                    ;/ Netzwerkpaket 
  pakBefehl.l                         ; Befehl in Zahl 
  pakLaenge.l                         ; Länge des Paketes 
  pakClientID.s                       ; ClientID von wem das Paket stammte 
  pakSucceed.b                        ; Angabe ob das Paket gültig ist 
  pakGUID.s                           ; GUID des Paketes. Identifikation des Clients. 
  pakData.s                           ; Daten die das Paket enthält. 
EndStructure

ConsoleColor(10,0)

OpenFile(0,"data.txt")
onlinemonth$=ReadString()
onlineyear$=ReadString()
CloseFile(0)

online=0
onlineday=0
onlinemonth=Val(onlinemonth$)
onlineyear=Val(onlineyear$)

Repeat
Buffer=AllocateMemory(1000)

 Sevent=NetworkServerEvent()
 
  Select Sevent  
    Case 1
    AddElement(ClientID())
    ClientID=NetworkClientID()
    online+1
    onlineday+1
    onlinemonth+1
    onlineyear+1
    OpenFile(0,"data.txt")
    WriteStringN(Str(onlinemonth))
    WriteStringN(Str(onlineyear))
    CloseFile(0)
    User = 1

  Case 2
    ReceiveNetworkData(ClientID, Buffer, 1000) 
    SplitNetPacket(PeekS(Buffer, 1000)) 
    ForEach PaketPool(): ParseNetPacketServer(@PaketPool(), ClientID): Next 
    ClearList(PaketPool())                            
    RtlFillMemory_(Buffer, 1000+1, 0)
    
    Case 4
    DeleteElement(ClientID())
    WriteString("Client verlassen")
    online-1
  EndSelect

;-Status
ConsoleLocate(0,2)
Print("Jetzt Online : "+Str(online))
ConsoleLocate(0,3)
Print("Heute Online : "+Str(onlineday))
ConsoleLocate(0,4)
Print("Im Monat online : "+Str(onlinemonth))
ConsoleLocate(0,5)
Print("Im Jahr online : "+Str(onlineyear))
ConsoleLocate(20,2)
Print(PeekS(Buffer))

If User=1
  ConsoleLocate(20,2)
  Print("Letzte ID: "+Str(ClientID))
EndIf 

FreeMemory(Buffer)
ForEver
natoll,jetzt muss ich noch einen Rechner zusammenbaun der 24 stunden am Tag online ist und meinen Server für mein Projekt Order of Blance laufen lässt
Benutzeravatar
MVXA
Beiträge: 3823
Registriert: 11.09.2004 00:45
Wohnort: Bremen, Deutschland
Kontaktdaten:

Beitrag von MVXA »

jo, da fehlen auch funktionen -_-. Ich hab gedacht du würdest sie selber proggen. Hier hast du die gesamte Netzwerk Include:

Code: Alles auswählen

NewList PaketPool.sNetPacket()

Procedure ParseNetPacketServer(*R_NetPacket.sNetPacket, ClientID)
    ...code...    
EndProcedure

Procedure ParseNetPacketClient(*R_NetPacket.sNetPacket)
    ...code...
EndProcedure

Procedure.b SplitNetPacket(ReceivedPacket.s)
    DefType.s tmpPacket, tmpNetData, tmpGUID
    DefType.l tmpPacketPtr, tmpLaenge, tmpBefehl
    
    Repeat
        tmpPacketPtr + 1
        tmpPacket = StringField(ReceivedPacket, tmpPacketPtr, Chr(4))
        If Len(tmpPacket) <> 0 
            tmpBefehl  = HexToLong(StringField(StringField(tmpPacket, 1, Chr(1)), 1, Chr(2)))
            tmpLaenge  = HexToLong(StringField(StringField(tmpPacket, 1, Chr(1)), 2, Chr(2)))
            tmpGUID    =           StringField(StringField(tmpPacket, 1, Chr(1)), 3, Chr(2))
            tmpNetData =                       StringField(tmpPacket, 2, Chr(1))
            If Len(tmpNetData) = tmpLaenge And Len(tmpPacket) > 10
                AddElement(PaketPool())
                Debugger("/CMD: " + Str(tmpBefehl) + "/LEN: " + Str(tmpLaenge) + "/GID: " + tmpGUID + "/DAT: " + tmpNetData)
                
                PaketPool()\pakBefehl   = tmpBefehl
                PaketPool()\pakLaenge   = tmpLaenge
                PaketPool()\pakGUID     = tmpGUID
                PaketPool()\pakData     = Base64Decode(tmpNetData)
                PaketPool()\pakSucceed  = #True 
                ByteReceived + tmpLaenge
            Else
                ; Fehlerroutine...
            EndIf
        EndIf 
    Until tmpPacket = ""
EndProcedure

Procedure.b SendNetPacket(lngBefehl.l, strGUID.s, strData.s, TCPClientID.l)
    DefType.l PaketLen, lngResult
    DefType.s tmpPaket 
    
    Debug strData
    strData = Base64Encode(strData)
    Debug strData
    tmpPaket = tmpPaket + RSet(Hex(lngBefehl), 4, "0")
    tmpPaket = tmpPaket + Chr(2)
    tmpPaket = tmpPaket + RSet(Hex(Len(strData)), 4, "0")
    tmpPaket = tmpPaket + Chr(2)
    tmpPaket = tmpPaket + strGUID
    
    tmpPaket = tmpPaket + Chr(1)
    tmpPaket = tmpPaket + strData
    tmpPaket = tmpPaket + Chr(4)
    
    PaketLen = Len(tmpPaket)
    *TCPSendBuffer = AllocateMemory(PaketLen+1)
    PokeS(*TCPSendBuffer, tmpPaket) 
    Debugger("Sending Buffer: " + PeekS(*TCPSendBuffer))
    
    SendNetworkData(TCPClientID, *TCPSendBuffer, PaketLen)
    Delay(2)
    ByteSended + PaketLen
    tmpPaket = ""
    
    RtlFillMemory_(*TCPSendBuffer, PaketLen+1, 0)
    FreeMemory(*TCPSendBuffer)
EndProcedure
Paketstruktur ist hier nochmal anders. Die in meinem 1. Post hatte ich aus dem Kopf. verzeiht mir mein Alzheimer ~_~.
Bild
Antworten