;|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ;| Titel....: Netzwerk Pakete ;| Datei....: NetworkPacket.pbi ;| Datum....: 09.09.2009 ;| Inhalt...: * Ermöglicht sicheres Senden (schreiben) ;| und Empfangen (lesen) von Netzwerkdaten ;|_____________________________________________________________________________ ; Vorrausgesetzte Includes ;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ; Konstanten ;¯¯¯¯¯¯¯¯¯¯¯¯¯¯ #NetworkPacketBuffer = 1024 ; Strukturen ;¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Structure NetworkPacket_PBI *MemoryBuffer *CurrentMemoryBuffer Length.l EndStructure Structure ReceiveNetworkPacket_PBI ConnectionID.i *NetworkPacket.NetworkPacket_PBI Finish.i EndStructure ; Arrays und LinkedLists ;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ Global NewList ReceiveNetworkPacket_PBI.ReceiveNetworkPacket_PBI() Global NetworkPacketMutex_PBI = CreateMutex() ; Proceduren und Macros ;¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯ ; Erstellt ein neues NetzwerkPaket Procedure CreateNetworkPacket(Length=#NetworkPacketBuffer, ConnectionID=0) Protected *NetworkPacket.NetworkPacket_PBI = AllocateMemory(SizeOf(NetworkPacket_PBI)) With *NetworkPacket If *NetworkPacket \MemoryBuffer = AllocateMemory(Length) \CurrentMemoryBuffer = \MemoryBuffer \Length = Length If \MemoryBuffer ProcedureReturn *NetworkPacket EndIf EndIf EndWith EndProcedure ; Löscht ein NetzwerkPaket und gibt den Speicher wieder frei Procedure DeleteNetworkPacket(*NetworkPacket.NetworkPacket_PBI) With *NetworkPacket FreeMemory(\MemoryBuffer) FreeMemory(*NetworkPacket) EndWith EndProcedure ; Sendet ein NetzwerkPaket an die ConnectionID Procedure SendNetworkPacket(*NetworkPacket.NetworkPacket_PBI, ConnectionID, DeleteNetworkPacket=#True) With *NetworkPacket Protected Length = \CurrentMemoryBuffer - \MemoryBuffer If SendNetworkData(ConnectionID, @Length, SizeOf(Long)) = SizeOf(Long) If SendNetworkData(ConnectionID, \MemoryBuffer, Length) = Length If DeleteNetworkPacket DeleteNetworkPacket(*NetworkPacket) EndIf ProcedureReturn #True EndIf EndIf EndWith EndProcedure ; Sendet ein NetzwerkPaket an eine Liste von ConnectionIDs Macro SendGroupNetworkPacket(NetworkPacket, ConnectionIDList) ForEach ConnectionIDList SendNetworkPacket(NetworkPacket, ConnectionIDList\ConnectionID, #False) Next DeleteNetworkPacket(NetworkPacket) EndMacro ; Empfängt alle bereit stehenden NetzwerkPakete Procedure ReceiveNetworkPacket(ConnectionID) Protected ReceiveLength, Length, Quit = #False Protected NewPackets = 0, NewLength Protected *ReceiveNetworkPacket_PBI.ReceiveNetworkPacket_PBI = #False ForEach ReceiveNetworkPacket_PBI() : With ReceiveNetworkPacket_PBI() If \ConnectionID = ConnectionID If Not \Finish *ReceiveNetworkPacket_PBI = @ReceiveNetworkPacket_PBI() Break EndIf EndIf EndWith : Next Repeat : With *ReceiveNetworkPacket_PBI\NetworkPacket If *ReceiveNetworkPacket_PBI Buffer = \Length-(\CurrentMemoryBuffer-\MemoryBuffer) ReceiveLength = ReceiveNetworkData(ConnectionID, \CurrentMemoryBuffer, Buffer) If ReceiveLength > 0 \CurrentMemoryBuffer + ReceiveLength If ReceiveLength >= Buffer-SizeOf(Long) \CurrentMemoryBuffer = \MemoryBuffer *ReceiveNetworkPacket_PBI\Finish = #True NewPackets + 1 If ReceiveLength = Buffer NewLength = PeekL(\MemoryBuffer+\Length-SizeOf(Long)) AddElement(ReceiveNetworkPacket_PBI()) ReceiveNetworkPacket_PBI()\ConnectionID = ConnectionID ReceiveNetworkPacket_PBI()\NetworkPacket = CreateNetworkPacket(NewLength+SizeOf(Long), ConnectionID) ReceiveNetworkPacket_PBI()\Finish = #False *ReceiveNetworkPacket_PBI = @ReceiveNetworkPacket_PBI() Continue EndIf EndIf EndIf Else ReceiveLength = ReceiveNetworkData(ConnectionID, @Length, SizeOf(Long)) If ReceiveLength = SizeOf(Long) AddElement(ReceiveNetworkPacket_PBI()) ReceiveNetworkPacket_PBI()\ConnectionID = ConnectionID ReceiveNetworkPacket_PBI()\NetworkPacket = CreateNetworkPacket(Length+SizeOf(Long), ConnectionID) ReceiveNetworkPacket_PBI()\Finish = #False *ReceiveNetworkPacket_PBI = @ReceiveNetworkPacket_PBI() Continue EndIf EndIf Break EndWith : ForEver ResetList(ReceiveNetworkPacket_PBI()) ProcedureReturn NewPackets EndProcedure ; Gibt das nächste zum auslesen bereite NetzwerkPaket zurück Procedure NextNetworkPacket(ConnectionID, *NetworkPacket.Integer=0) With ReceiveNetworkPacket_PBI() Repeat If Not NextElement(ReceiveNetworkPacket_PBI()) ProcedureReturn #False EndIf Until \ConnectionID = ConnectionID And \Finish EndWith If *NetworkPacket *NetworkPacket\i = ReceiveNetworkPacket_PBI()\NetworkPacket EndIf ProcedureReturn ReceiveNetworkPacket_PBI()\NetworkPacket EndProcedure ; Löscht alle NetzwerkPakete einer ConnectionID Procedure DeleteReceiveNetworkPacket(ConnectionID) ForEach ReceiveNetworkPacket_PBI() : With ReceiveNetworkPacket_PBI() If \ConnectionID = ConnectionID And \Finish DeleteNetworkPacket(\NetworkPacket) DeleteElement(ReceiveNetworkPacket_PBI()) EndIf EndWith : Next EndProcedure ; Sicheres Empfangen und Auslesen für Threads Macro LockReceiveNetworkPacket() LockMutex(NetworkPacketMutex_PBI) EndMacro Macro UnlockReceiveNetworkPacket() UnlockMutex(NetworkPacketMutex_PBI) EndMacro ; Interne Funktion zum vergrößern des Paketspeichers Procedure UpgradeNetworkPacket_PBI(*NetworkPacket.NetworkPacket_PBI, Length) With *NetworkPacket Protected MemoryBufferDifference = \CurrentMemoryBuffer - \MemoryBuffer If MemoryBufferDifference + Length > \Length \MemoryBuffer = ReAllocateMemory(\MemoryBuffer, \Length+(Int(Length/#NetworkPacketBuffer)+1)*#NetworkPacketBuffer) If \MemoryBuffer \Length + #NetworkPacketBuffer \CurrentMemoryBuffer = \MemoryBuffer + MemoryBufferDifference Else ProcedureReturn #False EndIf EndIf EndWith ProcedureReturn #True EndProcedure ; Scheibt eine Variable in das NetzwerkPaket Macro WriteNetworkPacket(TypeName, Type) Procedure WriteNetworkPacket#TypeName(*NetworkPacket.NetworkPacket_PBI, TypeName.Type) CompilerIf #PB_#TypeName = #PB_String If UpgradeNetworkPacket_PBI(*NetworkPacket, StringByteLength(String)+SizeOf(Character)) Poke#Type(*NetworkPacket\CurrentMemoryBuffer, TypeName) *NetworkPacket\CurrentMemoryBuffer + StringByteLength(String) + SizeOf(Character) ProcedureReturn #True EndIf CompilerElse If UpgradeNetworkPacket_PBI(*NetworkPacket, SizeOf(TypeName)) Poke#Type(*NetworkPacket\CurrentMemoryBuffer, TypeName) *NetworkPacket\CurrentMemoryBuffer + SizeOf(TypeName) ProcedureReturn #True EndIf CompilerEndIf EndProcedure EndMacro WriteNetworkPacket(Byte, b) WriteNetworkPacket(Character, c) WriteNetworkPacket(Word, w) WriteNetworkPacket(Long, l) WriteNetworkPacket(Quad, q) WriteNetworkPacket(Integer, i) WriteNetworkPacket(Float, f) WriteNetworkPacket(Double, d) WriteNetworkPacket(String, s) ; Liest eine Variable aus dem NetzwerkPaket Macro ReadNetworkPacket(TypeName, Type) Procedure.Type ReadNetworkPacket#TypeName(*NetworkPacket.NetworkPacket_PBI) Protected TypeName.Type = Peek#Type(*NetworkPacket\CurrentMemoryBuffer) CompilerIf #PB_#TypeName = #PB_String *NetworkPacket\CurrentMemoryBuffer + StringByteLength(String) + SizeOf(Character) CompilerElse *NetworkPacket\CurrentMemoryBuffer + SizeOf(TypeName) CompilerEndIf ProcedureReturn TypeName EndProcedure EndMacro ReadNetworkPacket(Byte, b) ReadNetworkPacket(Character, c) ReadNetworkPacket(Word, w) ReadNetworkPacket(Long, l) ReadNetworkPacket(Quad, q) ReadNetworkPacket(Integer, i) ReadNetworkPacket(Float, f) ReadNetworkPacket(Double, d) ReadNetworkPacket(String, s) ; Gibt die MemoryBufferPosition des NetzwerkPaketes zurück Procedure NetworkPacketID(*NetworkPacket.NetworkPacket_PBI) ProcedureReturn *NetworkPacket\MemoryBuffer EndProcedure ; Gibt die Position innerhalb des NetzwerkPaketes zurück Procedure NetworkPacketLoc(*NetworkPacket.NetworkPacket_PBI) ProcedureReturn *NetworkPacket\CurrentMemoryBuffer - *NetworkPacket\MemoryBuffer EndProcedure ; Ändert die Position innerhalb des NetzwerkPaketes auf die neue Position Procedure NetworkPacketSeek(*NetworkPacket.NetworkPacket_PBI, NewPosition) *NetworkPacket\CurrentMemoryBuffer = *NetworkPacket\MemoryBuffer + NewPosition EndProcedure CompilerIf 0 InitNetwork() ; Variante ; ServerEmpfang = 0 , ClientEmpfang = 1 #Variante = 1 ; Buffer ; wenn er teiler von Datenlänge ist BUG bei ClientEmpfang, sonst OK #Buffer = 8 *Buffer = AllocateMemory(32) CreateNetworkServer(1, 7000) ConnectionID = OpenNetworkConnection("127.0.0.1", 7000) Delay(100) Select NetworkServerEvent() Case #PB_NetworkEvent_Connect ClientID = EventClient() EndSelect Procedure Senden(ID) For n = 0 To 5 *Packet = CreateNetworkPacket() WriteNetworkPacketLong(*Packet, 123) WriteNetworkPacketString(*Packet, "Hallo hier da") WriteNetworkPacketByte(*Packet, 5) SendNetworkPacket(*Packet, ID) Delay(Random(200)+200) Next EndProcedure If #Variante ; Senden(ClientID) CreateThread(@Senden(),ClientID) ID = ConnectionID Else ; Senden(ConnectionID) CreateThread(@Senden(),ConnectionID) ID = ClientID EndIf Repeat If #Variante Event = NetworkClientEvent(ID) Else Event = NetworkServerEvent() EndIf Select Event Case #PB_NetworkEvent_Data Count = ReceiveNetworkPacket(ID) Debug "COUNT: "+Str(Count) If Count While NextNetworkPacket(ID, @*Packet) Debug "---" Debug ReadNetworkPacketLong(*Packet) Debug ReadNetworkPacketString(*Packet) Debug ReadNetworkPacketByte(*Packet) Wend DeleteReceiveNetworkPacket(ID) EndIf EndSelect Delay(1000) Until Quit Debug "Beendet" CompilerEndIf ; IDE Options = PureBasic 4.40 Beta 3 (Windows - x86) ; CursorPosition = 321 ; FirstLine = 311 ; EnableThread ; EnableXP