Server mit mehreren Puffer für ReceiveNetworkData() ?
- captain third
- Beiträge: 194
- Registriert: 12.12.2004 13:14
- Kontaktdaten:
Server mit mehreren Puffer für ReceiveNetworkData() ?
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?
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
- captain third
- Beiträge: 194
- Registriert: 12.12.2004 13:14
- Kontaktdaten:
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
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.
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

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
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
- captain third
- Beiträge: 194
- Registriert: 12.12.2004 13:14
- Kontaktdaten:
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
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
- captain third
- Beiträge: 194
- Registriert: 12.12.2004 13:14
- Kontaktdaten:
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
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?
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
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
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:
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:
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
<Befehl>[Byte 3]<Paketlänge>[Byte 3]<Client GUID>[Byte 2]<Base64Data>[Byte 4]
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)
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
- captain third
- Beiträge: 194
- Registriert: 12.12.2004 13:14
- Kontaktdaten:
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
jo, da fehlen auch funktionen -_-. Ich hab gedacht du würdest sie selber proggen. Hier hast du die gesamte Netzwerk Include:
Paketstruktur ist hier nochmal anders. Die in meinem 1. Post hatte ich aus dem Kopf. verzeiht mir mein Alzheimer ~_~.
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