Seite 1 von 1

ExamineDirectory() übers Netzwerk

Verfasst: 07.12.2010 21:24
von twain
Hallo,

ich versuch' mich mal seit Längerem wieder mit PB und bin etwas aus der Übung. Ich möchte ein (sehr simples) Fernwartungsprogramm schreiben, eigentlich nur zur Übung. Nun häng ich schon vor einem Problem: Ich will, ähnlich wie beí einem FTP-Server Verzeichnisse auflisten, nur funktioniert das Ganze nicht so wie ich will /:->
Das ganze sieht so aus, dass ich dem Client vom Server aus einen String schicke, und der mir dann das Verzeichnis aufgelistet zurückschicken soll:

Code: Alles auswählen

Enumeration
  #Directory
EndEnumeration


*TCPBuffer = AllocateMemory(1024)
Procedure GetList()
  *Buffer = AllocateMemory(1024)
        If ExamineDirectory(#Directory, text$, "*.*")

          While NextDirectoryEntry(#Directory)

            FileName$ = DirectoryEntryName(#Directory)
            If DirectoryEntryType(#Directory) = #PB_DirectoryEntry_Directory
              FileName$ = "[DIR] "+FileName$
            EndIf
            
            PokeS(*Buffer,FileName$)
            Debug "PeekS"+PeekS(*Buffer)
            SendNetworkData(ConnectionID,*Buffer,1024)
          Wend
          
        Else
          MessageRequester("Error","Can't examine this directory:")
        EndIf

EndProcedure


If InitNetwork() = 0
  MessageRequester("Error", "Can't initialize the network !", 0)
  End
EndIf

Port = 6000

ConnectionID = OpenNetworkConnection("127.0.0.1", Port)
If ConnectionID
  Repeat
   
   Select NetworkClientEvent(ConnectionID)
       
  Case 0     
       
  Case 2
      TCPBufferLength = ReceiveNetworkData(ConnectionID, *TCPBuffer, 1024)
      text$ = PeekS(*TCPBuffer,TCPBufferLength)
      Debug text$
        GetList()

  EndSelect
   
   
 Until  quit = 1
   
  FreeMemory(*TCPBuffer)

EndIf
  
End  
Bin mir sowieso nicht sicher, ob das so funktionieren kann. Und vorallem, wie groß der Buffer sein muss um große Verzeichnisse übermitteln zu können. Hier sagt er mir, dass die ConnectionID bei Getlist() 0 sei.
Debug "PeekS"+PeekS(*Buffer) ist hier nur als Test drinnen.

Der Server schaut so aus:

Code: Alles auswählen

Window()
CreateNetworkServer(0,6000)
    
  SEvent = NetworkServerEvent()
  ClientID = EventClient()
  
  Repeat
    
    *Buffer = AllocateMemory(5000)
    SEvent = NetworkServerEvent()
    ClientID = EventClient()
    EventID = WaitWindowEvent()
    
    If EventID = #PB_Event_Gadget
      
      Select EventGadget()
          
        Case #Button_List

          ;GetList()
          SendNetworkString(ClientID,"list")
          
        Case #Button_Connect
          
        Case #Button_Download

          SendNetworkString(ClientID,GetGadgetText(#String_Directory)+GetGadgetText(#Listview))


      EndSelect
    EndIf  
   
  Select SEvent
    Case  1
      AddGadgetItem(#Listview,-1,"Client verbunden")
      
    Case  2
      ReceiveNetworkData(ClientID,*Buffer,1024)
      ;AddGadgetItem(#Listview,-1,"Nachricht empfangen: "+PeekS(*Buffer))
      Debug PeekS(*Buffer)
      
    Case 3 
      ReceiveNetworkFile(ClientID,datei$)
      
    Case 4
      AddGadgetItem(#Listview,-1,"Clientverbindung verloren")
        
  EndSelect
  FreeMemory(*Buffer)
  Until EventID = #PB_Event_CloseWindow
End
Erstmal danke für die kommende Hilfe, hoffe ihr könnt mir weiterhelfen

Re: ExamineDirectory() übers Netzwerk

Verfasst: 07.12.2010 22:29
von STARGÅTE
Der Code hat leider sehr viele Problemstellen:
  • Du darfst auf der Server Seite nicht in der selben Schleife in der du NetworkServerEvent() abfragst, mit WaitWindowEvent() das ganze Programm anhalten, denn es heißt ja WaitWindowEvent, nicht WaitServerEvent() ;-) !
  • Auf beiden Seiten prüfst du nicht, ob ReceiveNetworkData(..., *Buffer,1024) überhaupt erfolgreich war, und wirklich die 1024 Bytes empfangen wurden.
  • Gleiches gilt für SendNetworkData(), denn wenn du zu schnell zu viele Daten Sendest, und die anderere Seite zu langsam ausließt, dann ist der Buffer irgendwann voll und es sendet nicht mehr.
  • Immer 1024 Bytes zu senden obwohl der Name vllt nicht mal 100 Zeichen hat, funktioniert zwar, weil PeekS() auf der anderen Seite nach der NULL eh abbricht, aber ist meiner Meinung nach unnötig.
  • Die ConnectionID ist in deiner prozedur 0, weil du sie ja garnicht an die Prozedur übergibst, und sie nicht Global ist!
  • gleiches gilt für text$
Weitere Sachen zum Thema Netzwerk Daten senden und empfangen findest du im Forum genug:
- Daten können verschmelzen, Daten können geteil werden, usw.

Ich hoffe du kannst mit meiner Hilfe-Liste gut arbeiten ...

Re: ExamineDirectory() übers Netzwerk

Verfasst: 07.12.2010 23:10
von Bisonte
Ich sehe, dass dort jeder Directory Eintrag einzelnd gesendet wird.
Wäre es nicht (Datenstromtechnisch) effizienter, das komplette Directory einzulesen,
zu packen und dann komplett zu verschicken ?
Hätte auch den Vorteil, dass dann die Speichergrösse bekannt ist usw. (Für SendNetworkData())

Grob gesagt : Textfile mit Directory erstellen, mit den Packer Befehlen schrumpfen und dann senden ?
Oder denk ich da jetzt zu umständlich ? (Könnte natürlich auch direkt im Speicher packen und dann senden)

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 00:15
von twain
Erstmal ein Danke euch beide :mrgreen:

Ok, das mit den überprüfen ist klar, verbesser ich natürlich noch. Auf das Global hät ich auch selber draufkommen können :/ ^^ aber das was mir unklar ist, ist das Schleifenproblem. Soll ich zwei Schleifen machen? also eine mit WaitWindowEvent() und einmal mit NetworkServerEvent()? und wie soll ich die abgrenzen? Kann ich das so ungefähr machen?

Code: Alles auswählen

Repeat
  Repeat
 If EventID = #PB_Event_Gadget
      
      Select EventGadget()
.
.
  Until EventID = #PB_Event_CloseWindow
EndIf
Select SEvent
.
.
ForEver
Zu Bisonte:

ist an und für sich keine verkehrte Idee, wie genau ich das umsetzen werde weiß ich noch nicht. Ich schau mal wie die Daten schneller ankommen

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 00:31
von STARGÅTE
Kommt doch aufs selbe hinaus ...
WaitWindowEvent() hält die Programmausführung an, und zwar genau an dieser Stelle, bis ein Event auf dem Fenster kommt.
Das heißt er springt auch nicht aus deiner neuen inneren Schleife und erreicht immer noch nicht das NetworkServerEvent()

Du müsstest das Wait ganz entfernen und durch ein normales WindowEvent()

Und damit die CPU nicht leidet kannst ein ein Delay(2) oder so einfügen wenn es KEIN WindowEvent() und KEIN NetworkServerEvent() gibt.

Oder du benutzt Threads ...

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 01:13
von Bisonte
STARGÅTE hat geschrieben: Und damit die CPU nicht leidet kannst ein ein Delay(2) oder so einfügen wenn es KEIN WindowEvent() und KEIN NetworkServerEvent() gibt.
reicht da nicht das vielgelobte " WaitWindowEvent(2) " für aus ?
Wenn kein WindowEvent anliegt gehts automatisch nach 2 ms weiter...

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 01:24
von STARGÅTE
In deinem Fall vermutlich schon,

Weil es vermutlich reicht "nur" 500 mal / Sekunde NetworkServerEvent() aufzurufen.

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 02:36
von Bisonte
Bleibt denn nicht ein ServerEvent solange, bis es abgearbeitet werden kann ?

So wie beim WindowEvent... man kann ja auch ne 1 als delay nehem ;)

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 09:49
von Kiffi
@twain: Um jetzt noch einmal einen ganz anderen Ansatz in's Spiel
zu bringen (und auf die Gefahr hin, wieder als Cheater bezeichnet
zu werden ;-)): Es gibt ein kostenloses Tool namens Everything (Win only),
welches Festplattenverzeichnisse über den direkten Zugriff auf NTFS-Einträge
ausliest. Das ganze geht rasend schnell und ressourcensparend.

Das besondere an diesem Tool: Es stellt einen HTML- und / oder FTP-Server
zur Verfügung, welche(n) man direkt ansprechen kann. Somit hättest Du
zumindest die Server-Komponente gespart.

Grüße ... Kiffi

Re: ExamineDirectory() übers Netzwerk

Verfasst: 08.12.2010 14:05
von twain
Ich hab einfach mal WindowEvent() genommen um das Thema mit den Events abzuschließen :lol:
@Kiffi: Natürlich gibt es für alles auch fertige Lösungen, aber für was dann programmieren lernen? xD Danke für deinen Beitrag, das Programm sieht wirklich gut aus, nur werde ich es nicht verwenden^^