Seite 1 von 1

Netzwerk Server und Client (Thread basiert)

Verfasst: 01.09.2008 01:52
von gnasen
Da man nicht nur nehmen sondern auch geben soll, will ich meine Netzwerk-Erweiterung vorstellen.

Bisher haben Bison und ich diese getestet und keine Bugs finden können.

Es handelt sich um eine Server-Client Verbindung die zurzeit dem Senden von Strings dient.

Das ganze ist Thread basiert und die Nachrichten werden mit einem Schlüssel markiert, damit auch sicher alles ankommt, selbst wenn die Nachricht unterwegs aus mysteriösen Gründen zerteilt oder mit anderen aneinander gehangen werden sollte.

Schauts euch einfach an, ich freue mich übers Feedback.

Die Kommentierung ist primär im Client vorhanden, da beides fast identisch funktioniert.


Der Client:

Code: Alles auswählen

; Alles hier zur freien Verfügung, macht damit was ihr woll ;)
; 
; Hierbei handelt es sich um eine mögliche Anwendung der Network-Befehle zum Versenden von Informationen.
; Das ganze ist nach folgender Idee aufgebaut: Eine Nachricht besteht aus folgender Structure:
; 
; Net_ID     -> Netzwerk-ID des Users
; Net_Event  -> Welche Art von Event? Es gibt connect, disconnect und data
; Net_Text   -> Der Inhalt der Nachricht, immer ein String (könnte aber auch für Datenbuffer angepasst werden)
; Net_Typus  -> Der typus dient der Identifikation (zB. Nachricht, SpielerPositionen etc.)
; Net_Time   -> Die Zeit, zu der Die Nachricht eingetroffen ist
; 
; Beachtet werden muss nur: Die Erstellung, Das Verschicken und Das Auswerten von Nachrichten, dazu mehr im Quellcode
; Zusätzliches ist alles Thread basiert, welches das Senden und Empfangen unabhängig von der Hauptschleife macht.
;
; Dies ist die Lite Version, es fehlt beim Schließen das sichere Verlassen des Threads, sowie der Mutex für die IP Übergabe.
; Habe es aus Gründen der Übersicht ersteinmal weggelassen
;
;/ Diesen Test im DEBUGGER starten
;
; Da Server und Client fast identisch sind, habe ich ersteinmal nur den Client kommentiert,
; Die Unterschiede liegen nur im Detail und sind nicht relevant.
;

EnableExplicit

Enumeration ;Net_Typus deklaration (Die Arten der Nachrichten)
  
  #typus_Nachricht_ohne_Echo
  #typus_Nachricht_mit_Echo
  
EndEnumeration

; Die confidence_Long dient einfach nur als Hinweis einer möglichen neuen Nachricht im Buffer, kann einen belieben Wert haben
#confidence_long = 132592154

; Port und Server sollten klar sein. Vorsicht wegen dem Thread und IP.s (evtl noch Mutex setzen)
#Port            = 5566
Global IP.s      = "127.0.0.1"

Structure Net_Events
  
  Net_ID.l
  Net_Event.l
  Net_Text.s
  Net_Typus.l
  Net_Time.l
  
EndStructure

Structure Net_Send
  
  Net_ID.l
  Net_Typus.l
  Net_Text.s
  
EndStructure

Structure storeNET
  
  StoreClient.l
  StoreBuffer.l
  StoreTime.l
  
EndStructure

; Diese hier müssen sein
Global NewList NetEvents.Net_Events()
Global NewList NetSend.Net_Send()
Global Mutex.l = CreateMutex()
; Diese hier kann man noch anders verpacken bei Bedarf
Global ClientThreadID.l = 0
Global ServerID.l


;- DoNetEvents kümmert sich um die Bearbeitung der Daten, einfach die gewünschten Reaktionen eintragen
Procedure DoNetEvents()
  
  ForEach NetEvents()
    
    Select NetEvents()\Net_Event
      
      Case #PB_NetworkEvent_Data
        
        Select NetEvents()\Net_Typus
          
          Case #typus_Nachricht_ohne_Echo
            Debug "Client empfängt: " + Str(NetEvents()\Net_ID) + " typus: " + Str(NetEvents()\Net_Typus) + " Zeit: " + Str(NetEvents()\Net_Time) + " text: " + NetEvents()\Net_Text
          Case #typus_Nachricht_mit_Echo
            ;nichts tun
            
        EndSelect
        
    EndSelect
    
  Next
  
  ClearList(NetEvents())
  
EndProcedure

; Wird benutzt um Daten zu senden. WICHTIG: Nicht direkt benutzen, sondern über AddSend gehen !!!
Procedure SendString(ConID.l, typus.l, text.s)
  
  Protected ByteLength.l = 4+Len(text)+1
  Protected *buffer.l = AllocateMemory(ByteLength)
  Protected *out.l    = AllocateMemory(4+4+4+ByteLength)
  
  PokeL(*buffer, typus)
  PokeS(*buffer+4, text)
  
  PokeL(*out,    #confidence_long)
  PokeL(*out+4,  ByteLength)
  PokeL(*out+8,  CRC32Fingerprint(*buffer,ByteLength))
  PokeL(*out+12, typus)
  PokeS(*out+16, text)
  
  If ConID
    
    SendNetworkData(ConID, *out, 12+ByteLength)
    
  EndIf 
  
  FreeMemory(*buffer)
  FreeMemory(*out)
  
EndProcedure

;- Diese Funktion benutzen um Daten zu versenden. Diese kommen auf den Netzwerkstapel.
Procedure AddSend(ConID.l, typus.l, text.s)
  
  AddElement(NetSend())
  NetSend()\Net_ID    = ConID
  NetSend()\Net_Typus = typus
  NetSend()\Net_Text  = text
  
EndProcedure

; Hierbei handelt es sich um den Thread, welcher das Empfangen und senden verarbeitet.
Procedure CreateThreadClient(dummy.l)
  
  ;NetzwerkInput verarbeiten
  
  Protected NewList StoreNetwork.storeNET()
  
  Protected CeventID.l
  Protected clientID.l
  Protected NewList NetEventsStore.Net_Events()
  Protected NewList NetSendStore.Net_Send()
  
  ServerID = OpenNetworkConnection(IP.s, #Port)
  
  If ServerID
    
    Repeat
      
      ;/ Server Loop
      
      CeventID = NetworkClientEvent(ServerID) 
      
      If CeventID
        
        clientID = EventClient()
        
        Select CeventID
          
          Case #PB_NetworkEvent_Data
            
            Protected *income.l   = AllocateMemory(1024)
            Protected *complete.l = AllocateMemory(1)
            Protected Durchgang.l = 0
            Protected ReceivedBytes.l = 0
            
            Protected StoreSize.l = 0
            Protected completeSize.l = 0
            
            Repeat 
              ReceivedBytes = ReceiveNetworkData(ServerID, *income, 1024)
              *complete = ReAllocateMemory(*complete, (1024*(Durchgang+1))-(1024-ReceivedBytes))
              completeSize = (1024*(Durchgang+1))-(1024-ReceivedBytes)
              If *complete
                CopyMemory(*income, *complete+1024*(Durchgang), ReceivedBytes)
                Durchgang+1
              Else
                ReceivedBytes = 0
              EndIf
            Until ReceivedBytes <> 1024  
            
            
            ForEach StoreNetwork()
              If (ElapsedMilliseconds() - StoreNetwork()\StoreTime) < 500
                If StoreNetwork()\StoreClient = clientID
                  
                  StoreNetwork()\StoreBuffer
                  StoreSize = MemorySize(StoreNetwork()\StoreBuffer)
                  
                  *complete = ReAllocateMemory(*complete, StoreSize+completeSize)
                  
                  MoveMemory(*complete, *complete+StoreSize, completeSize)
                  
                  CopyMemory(StoreNetwork()\StoreBuffer, *complete, StoreSize)
                  
                  FreeMemory(StoreNetwork()\StoreBuffer)
                  DeleteElement(StoreNetwork())
                  
                EndIf
              Else
                FreeMemory(StoreNetwork()\StoreBuffer)
                DeleteElement(StoreNetwork())
              EndIf
            Next
            
            Protected currentByte.l   = 0
            Protected BreakPoint.l    = 0
            Protected StoreToBuffer.l = *complete
            
            Protected In_Length.l      = 0
            Protected In_FingerPrint.l = 0
            Protected In_Typus.l       = 0
            Protected In_String.s      = ""
            
            currentByte = *complete
            BreakPoint  = *complete + completeSize + StoreSize
            
            Repeat
              
              If PeekL(currentByte) = #confidence_long
                
                In_Length      = PeekL(currentByte +  4)
                In_FingerPrint = PeekL(currentByte +  8)
                In_Typus       = PeekL(currentByte + 12)
                
                If In_Length <= (BreakPoint - (currentByte + 12)) And In_Length > 0
                  
                  If CRC32Fingerprint(currentByte + 12, In_Length) = In_FingerPrint
                    
                    In_String = PeekS(currentByte + 16)
                    
                    AddElement(NetEventsStore())
                    NetEventsStore()\Net_ID    = clientID
                    NetEventsStore()\Net_Event = #PB_NetworkEvent_Data
                    NetEventsStore()\Net_Time  = ElapsedMilliseconds()
                    NetEventsStore()\Net_Typus = In_Typus
                    NetEventsStore()\Net_Text  = In_String
                    
                    currentByte + In_Length + 12
                    StoreToBuffer = currentByte
                    
                    Continue
                    
                  EndIf
                  
                EndIf
                
              EndIf
              
              currentByte + 1
              
            Until currentByte => BreakPoint
            
            If StoreToBuffer < BreakPoint
              
              AddElement(StoreNetwork())
              StoreNetwork()\StoreClient = clientID
              StoreNetwork()\StoreBuffer = AllocateMemory( (*complete + MemorySize(*complete)) - (StoreToBuffer) )
              
              CopyMemory(*complete, StoreNetwork()\StoreBuffer, (*complete + MemorySize(*complete)) - (StoreToBuffer))
              
              StoreNetwork()\StoreTime   = ElapsedMilliseconds()
              
            EndIf
            
            FreeMemory(*complete)
            FreeMemory(*income)
            
            
        EndSelect
        
      EndIf
      
      ;/ Daten übertragen
      
      If TryLockMutex(Mutex)
        
        ForEach NetEventsStore()
          
          AddElement(NetEvents())
          NetEvents()\Net_ID    = NetEventsStore()\Net_ID
          NetEvents()\Net_Event = NetEventsStore()\Net_Event
          NetEvents()\Net_Time  = NetEventsStore()\Net_Time
          NetEvents()\Net_Typus = NetEventsStore()\Net_Typus
          NetEvents()\Net_Text  = NetEventsStore()\Net_Text
          
        Next
        
        ClearList(NetEventsStore())
        
        ForEach NetSend()
          
          AddElement(NetSendStore())
          NetSendStore()\Net_ID    = NetSend()\Net_ID
          NetSendStore()\Net_Typus = NetSend()\Net_Typus
          NetSendStore()\Net_Text  = NetSend()\Net_Text
          
        Next
        
        ClearList(NetSend())
        
        
        ;/ Net Sends rausschicken
        
        ForEach NetSendStore()
          
          SendString(NetSendStore()\Net_ID, NetSendStore()\Net_Typus, NetSendStore()\Net_Text)
          
        Next
        
        ClearList(NetSendStore())
        
        
        UnlockMutex(Mutex)
        
      EndIf
      
      Delay(1)
      
    ForEver
    
  EndIf
  
EndProcedure


;/ Los gehts...

If Not InitNetwork()
  Debug "nix InitNetwork()"
  End
EndIf

OpenWindow(0,0,0,100,100,"client")

ClientThreadID = CreateThread(@CreateThreadClient(),0)
Delay(500)

Debug "---Start Client---"

Define EventID.l
Define a.l

; Einfach mal 1000 Nachrichten auf den Stapel
For a=0 To 1000
  AddSend(ServerID,#typus_Nachricht_mit_Echo,"hallo " + Str(a))
Next


Repeat
  
  EventID = WindowEvent()
  
  LockMutex(Mutex)
  
  ; Dieser Aufruf verarbeitet alle eingegangenen Nachrichten. Mutexe nicht vergessen !
  DoNetEvents()
  
  UnlockMutex(Mutex)
  
  Delay(1)
  
Until EventID = #PB_Event_CloseWindow


Der Server:

Code: Alles auswählen

; Alles hier zur freien Verfügung, macht damit was ihr woll ;)
; 
; Hierbei handelt es sich um eine mögliche Anwendung der Network-Befehle zum Versenden von Informationen.
; Das ganze ist nach folgender Idee aufgebaut: Eine Nachricht besteht aus folgender Structure:
; 
; Net_ID     -> Netzwerk-ID des Users
; Net_Event  -> Welche Art von Event? Es gibt connect, disconnect und data
; Net_Text   -> Der Inhalt der Nachricht, immer ein String (könnte aber auch für Datenbuffer angepasst werden)
; Net_Typus  -> Der typus dient der Identifikation (zB. Nachricht, SpielerPositionen etc.)
; Net_Time   -> Die Zeit, zu der Die Nachricht eingetroffen ist
; 
; Beachtet werden muss nur: Die Erstellung, Das Verschicken und Das Auswerten von Nachrichten, dazu mehr im Quellcode
; Zusätzliches ist alles Thread basiert, welches das Senden und Empfangen unabhängig von der Hauptschleife macht.
;
; Dies ist die Lite Version, es fehlt beim Schließen das sichere Verlassen des Threads, sowie der Mutex für die IP Übergabe.
; Habe es aus Gründen der Übersicht ersteinmal weggelassen
;
;/ Diesen Test im DEBUGGER starten
;
; Da Server und Client fast identisch sind, habe ich ersteinmal nur den Client kommentiert,
; Die Unterschiede liegen nur im Detail und sind nicht relevant.
;

EnableExplicit

Enumeration ;Typus
  
  #typus_Nachricht_ohne_Echo
  #typus_Nachricht_mit_Echo
  
EndEnumeration

#confidence_long = 132592154
#Port            = 5566

Structure Net_Events
  
  Net_ID.l
  Net_Event.l
  Net_Text.s
  Net_Typus.l
  Net_Time.l
  
EndStructure

Structure Net_Send
  
  Net_ID.l
  Net_Typus.l
  Net_Text.s
  
EndStructure

Structure storeNET
  
  StoreClient.l
  StoreBuffer.l
  StoreTime.l
  
EndStructure

Global NewList NetEvents.Net_Events()
Global NewList NetSend.Net_Send()
Global Mutex.l = CreateMutex()
Global ServerThreadID.l = 0

Procedure AddSend(ConID.l, typus.l, text.s)
  
  AddElement(NetSend())
  NetSend()\Net_ID    = ConID
  NetSend()\Net_Typus = typus
  NetSend()\Net_Text  = text
  
EndProcedure

Procedure DoNetEvents()

  ForEach NetEvents()
    
    Select NetEvents()\Net_Event
      
      Case #PB_NetworkEvent_Connect
        
        Debug "Client ID: " + Str(NetEvents()\Net_ID) + " connected"
        
      Case #PB_NetworkEvent_Disconnect
        
        Debug "Client ID: " + Str(NetEvents()\Net_ID) + " disconnected"
        
      Case #PB_NetworkEvent_Data
         
        Select NetEvents()\Net_Typus
          
          Case #typus_Nachricht_ohne_Echo
            ;do this
          Case #typus_Nachricht_mit_Echo
            Debug "Server empfängt: " + Str(NetEvents()\Net_ID) + " typus: " + Str(NetEvents()\Net_Typus) + " Zeit: " + Str(NetEvents()\Net_Time) + " text: " + NetEvents()\Net_Text
            AddSend(NetEvents()\Net_ID, #typus_Nachricht_ohne_Echo, "echo " + NetEvents()\Net_Text)
          
        EndSelect

    EndSelect
    
  Next
  
  ClearList(NetEvents())
  
EndProcedure

Procedure SendString(ConID.l, typus.l, text.s)
  
  Protected ByteLength.l = 4+Len(text)+1
  Protected *buffer.l = AllocateMemory(ByteLength)
  Protected *out.l    = AllocateMemory(4+4+4+ByteLength)
  
  PokeL(*buffer, typus)
  PokeS(*buffer+4, text)
  
  PokeL(*out,    #confidence_long)
  PokeL(*out+4,  ByteLength)
  PokeL(*out+8,  CRC32Fingerprint(*buffer,ByteLength))
  PokeL(*out+12, typus)
  PokeS(*out+16, text)
  
  If ConID
    
    SendNetworkData(ConID, *out, 12+ByteLength)
    
  EndIf 
  
  FreeMemory(*buffer)
  FreeMemory(*out)
  
EndProcedure

Procedure CreateThreadServer(dummy.l)
  
  ;NetzwerkInput verarbeiten
  
  Protected NewList StoreNetwork.storeNET()
  
  Protected SeventID.l
  Protected clientID.l
  Protected ServerID.l
  Protected NewList NetEventsStore.Net_Events()
  Protected NewList NetSendStore.Net_Send()
  
  ServerID = CreateNetworkServer(#PB_Any, #Port, #PB_Network_TCP)
  
  If ServerID
    
    Repeat
      
      ;/ Server Loop
      
      SeventID = NetworkServerEvent() 
      
      If SeventID
        
        clientID = EventClient()
        
        Select SeventID
          
          Case #PB_NetworkEvent_Connect
            
            AddElement(NetEventsStore())
            NetEventsStore()\Net_ID    = clientID
            NetEventsStore()\Net_Event = #PB_NetworkEvent_Connect
            NetEventsStore()\Net_Time  = ElapsedMilliseconds()
            NetEventsStore()\Net_Typus = 0
            NetEventsStore()\Net_Text  = ""
            
          Case #PB_NetworkEvent_Disconnect
            
            AddElement(NetEventsStore())
            NetEventsStore()\Net_ID    = clientID
            NetEventsStore()\Net_Event = #PB_NetworkEvent_Disconnect
            NetEventsStore()\Net_Time  = ElapsedMilliseconds()
            NetEventsStore()\Net_Typus = 0
            NetEventsStore()\Net_Text  = ""
            
          Case #PB_NetworkEvent_Data
            
            Protected *income.l   = AllocateMemory(1024)
            Protected *complete.l = AllocateMemory(1)
            Protected Durchgang.l = 0
            Protected ReceivedBytes.l = 0
            
            Protected StoreSize.l = 0
            Protected completeSize.l = 0
            
            Repeat 
              ReceivedBytes = ReceiveNetworkData(clientID, *income, 1024)
              *complete = ReAllocateMemory(*complete, (1024*(Durchgang+1))-(1024-ReceivedBytes))
              completeSize = (1024*(Durchgang+1))-(1024-ReceivedBytes)
              If *complete
                CopyMemory(*income, *complete+1024*(Durchgang), ReceivedBytes)
                Durchgang+1
              Else
                ReceivedBytes = 0
              EndIf
            Until ReceivedBytes <> 1024  
            
            
            ForEach StoreNetwork()
              If (ElapsedMilliseconds() - StoreNetwork()\StoreTime) < 500
                If StoreNetwork()\StoreClient = clientID
                  
                  StoreNetwork()\StoreBuffer
                  StoreSize = MemorySize(StoreNetwork()\StoreBuffer)
                  
                  *complete = ReAllocateMemory(*complete, StoreSize+completeSize)
                  
                  MoveMemory(*complete, *complete+StoreSize, completeSize)
                  
                  CopyMemory(StoreNetwork()\StoreBuffer, *complete, StoreSize)
                  
                  FreeMemory(StoreNetwork()\StoreBuffer)
                  DeleteElement(StoreNetwork())
                  
                EndIf
              Else
                FreeMemory(StoreNetwork()\StoreBuffer)
                DeleteElement(StoreNetwork())
              EndIf
            Next
            
            Protected currentByte.l   = 0
            Protected BreakPoint.l    = 0
            Protected StoreToBuffer.l = *complete
            
            Protected In_Length.l      = 0
            Protected In_FingerPrint.l = 0
            Protected In_Typus.l       = 0
            Protected In_String.s      = ""
            
            currentByte = *complete
            BreakPoint  = *complete + completeSize + StoreSize
            
            Repeat
              
              If PeekL(currentByte) = #confidence_long
                
                In_Length      = PeekL(currentByte +  4)
                In_FingerPrint = PeekL(currentByte +  8)
                In_Typus       = PeekL(currentByte + 12)
                
                If In_Length <= (BreakPoint - (currentByte + 12)) And In_Length > 0
                  
                  If CRC32Fingerprint(currentByte + 12, In_Length) = In_FingerPrint
                    
                    In_String = PeekS(currentByte + 16)

                    AddElement(NetEventsStore())
                    NetEventsStore()\Net_ID    = clientID
                    NetEventsStore()\Net_Event = #PB_NetworkEvent_Data
                    NetEventsStore()\Net_Time  = ElapsedMilliseconds()
                    NetEventsStore()\Net_Typus = In_Typus
                    NetEventsStore()\Net_Text  = In_String
                    
                    currentByte + In_Length + 12
                    StoreToBuffer = currentByte
                    
                    Continue
                    
                  EndIf
                  
                EndIf
                
              EndIf
              
              currentByte + 1
              
            Until currentByte => BreakPoint
            
            If StoreToBuffer < BreakPoint
              
              AddElement(StoreNetwork())
              StoreNetwork()\StoreClient = clientID
              StoreNetwork()\StoreBuffer = AllocateMemory( (*complete + MemorySize(*complete)) - (StoreToBuffer) )
              
              CopyMemory(*complete, StoreNetwork()\StoreBuffer, (*complete + MemorySize(*complete)) - (StoreToBuffer))
              
              StoreNetwork()\StoreTime   = ElapsedMilliseconds()
              
            EndIf
            
            FreeMemory(*complete)
            FreeMemory(*income)
            
            
        EndSelect
        
      EndIf
      
      ;/ Daten übertragen
      
      If TryLockMutex(Mutex)
        
        ForEach NetEventsStore()
          
          AddElement(NetEvents())
          NetEvents()\Net_ID    = NetEventsStore()\Net_ID
          NetEvents()\Net_Event = NetEventsStore()\Net_Event
          NetEvents()\Net_Time  = NetEventsStore()\Net_Time
          NetEvents()\Net_Typus = NetEventsStore()\Net_Typus
          NetEvents()\Net_Text  = NetEventsStore()\Net_Text
          
        Next
        
        ClearList(NetEventsStore())
        
        ForEach NetSend()
          
          AddElement(NetSendStore())
          NetSendStore()\Net_ID    = NetSend()\Net_ID
          NetSendStore()\Net_Typus = NetSend()\Net_Typus
          NetSendStore()\Net_Text  = NetSend()\Net_Text
          
        Next
        
        ClearList(NetSend())
        
        
        ;/ Net Sends rausschicken
        
        ForEach NetSendStore()
          
          SendString(NetSendStore()\Net_ID, NetSendStore()\Net_Typus, NetSendStore()\Net_Text)
          
        Next
        
        ClearList(NetSendStore())
        
        
        UnlockMutex(Mutex)
        
      EndIf
      
      Delay(1)
      
    ForEver
    
  EndIf
  
EndProcedure


;/ Los gehts...

If Not InitNetwork()
  Debug "nix InitNetwork()"
  End
EndIf

OpenWindow(0,0,0,100,100,"server")

ServerThreadID = CreateThread(@CreateThreadServer(),0)
Delay(500)

Debug "---Start Server---"

Define EventID.l

Repeat
  
  EventID = WindowEvent()
  
  LockMutex(Mutex)
  
  ;/ Alle Net Events auswerten
  
  DoNetEvents()
  
  UnlockMutex(Mutex)
  
  Delay(1)
  
Until EventID = #PB_Event_CloseWindow


Sieht vllt nach mehr aus, als es ist. Sollte nach kurzer Eingewöhnung nur so flutschen im Netz ;)

Verfasst: 01.09.2008 09:43
von Dostej
klingt von der Beschriebugn her gut
Werds mal stesten heute abend

Verfasst: 01.09.2008 22:32
von gnasen
hmm keiner wills testen?

Verfasst: 01.09.2008 22:44
von STARGÅTE
01 Sep 2008 1:52:17
01 Sep 2008 22:32:32
--------------------------
20h 40min 15s

also gib mir und anderen noch etwas zeit.

Verfasst: 01.09.2008 22:54
von HeX0R

Code: Alles auswählen

Procedure CreateThreadClient() 
Niemals, unter gar keinen Umständen, eine Threadprozedur ohne Parameter benutzen!
Auch, wenn du keine Parameter brauchst, setz nen Dummy.l rein.

Verfasst: 01.09.2008 23:14
von gnasen
habe ich hinzugefügt, auch wenn sich mir der Sinn nicht ganz erschließt. Ich wusste zwar, dass man bei CreateThread() einen Parameter übergeben soll, aber warum muss die Thread-Prozedur einen haben?

Warum überhaupt meine ich damit

Verfasst: 01.09.2008 23:58
von Thorium
gnasen hat geschrieben:habe ich hinzugefügt, auch wenn sich mir der Sinn nicht ganz erschließt. Ich wusste zwar, dass man bei CreateThread() einen Parameter übergeben soll, aber warum muss die Thread-Prozedur einen haben?

Warum überhaupt meine ich damit
Weil das in der WinAPI so vorgesehen ist. Es wird _immer_ ein Parameter übergeben. PB könnte natürlich was drumrumbasteln, das der Parameter optional wird. Aber wozu der Umstand, wenn man sich einfach ein Dummy.l in die Prozedur packen kann.

Wie gesagt ist eine WinAPI spezifische Geschichte.