sendnetworkstring question to fred and one to all

Everything else that doesn't fall into one of the other PB categories.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

Hi Fred!

You told me some time ago that you have removed the SendNetworkString and the ReceiveNetworkString, but its still implemented in 3.20. Is it now working properly or is it still buggy?

By the way, could anyone give a short PB x-ample how to send and receive datas via the network CORRECTLY!? I fuxx it up all the last month. Everytime I tried I loose datas on the Clientside by receiving the datas. Its a hazle. Please, could anyone help!?

Mike

Tranquilizer/ Secretly!
Registred PureBasic User
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
By the way, could anyone give a short PB x-ample how to send and receive datas via the network CORRECTLY!? I fuxx it up all the last month. Everytime I tried I loose datas on the Clientside by receiving the datas. Its a hazle. Please, could anyone help!?
Don't know if it's short but it isn't long either :wink: Ok here goes, one server coming up:

Code: Select all

; Server
; Example by Pupil 2002/06/21

Global threadmessage.l, threadanswer.l

Declare NetworkProc(foo.l)



If InitNetwork() = 0
  Debug "Initnetwork failed!"
  End
EndIf

port.l = 5555

If OpenWindow(0, 100, 100, 300, 100, #PB_Window_SystemMenu, "Server") = 0
  Debug "OpenWindow failed!"
  End
EndIf
 
If CreateGadgetList(WindowID(0))
  ButtonGadget(0, 5,5, 100, 20, "Start Server")
  ButtonGadget(1, 5, 30, 100, 20, "Stop Server")
  DisableGadget(1, 1)
Else
  Debug "Couldn't create gadgets!"
  End
EndIf

Repeat
  event.l = WaitWindowEvent()
    
  Select event
    Case #PB_EventGadget
      Select EventGadgetID()
        Case 0
          If CreateNetworkServer(port)
            DisableGadget(0, 1)
            DisableGadget(1, 0)
            threadmessage = 0
            CreateThread( @NetworkProc(), 0)
          EndIf
        Case 1
          threadmessage = 1
          While threadanswer = 0
            Delay(1)
          Wend
          CloseNetworkServer()
          DisableGadget(0, 0)
          DisableGadget(1, 1)
      EndSelect
    Case #PB_EventCloseWindow
      quit = 1
  EndSelect
Until quit
End

DisableDebugger

Procedure NetworkProc(foo.l)
  threadanswer = 0
  Repeat
    netevent = NetworkServerEvent()
    If netevent
      clientid = NetworkClientID()
      Select netevent
        Case 1 ; Client connected
          If OpenFile(0, "serverlog.txt")
            FileSeek(Lof())
            WriteStringN("Client $"+Hex(clientid)+" connected..")
            CloseFile(0)
          EndIf
        Case 4 ; Client disconnected
          If OpenFile(0, "serverlog.txt")
            FileSeek(Lof())
            WriteStringN("Client $"+Hex(clientid)+" disconnected..")
            CloseFile(0)
          EndIf
        Default ; Data has been received
          *buffer = AllocateMemory(0, 2048, 0)
          Repeat
            length = ReceiveNetworkData(clientid, *buffer, 2048)
            If length
              If OpenFile(0, "serverlog.txt")
                FileSeek(Lof())
                WriteData(*buffer, length)
                CloseFile(0)
              EndIf
            EndIf
          Until length = 0
      EndSelect
    Else
      Delay(1)
    EndIf
  Until threadmessage
  threadanswer = 1
EndProcedure
And one Client coming right here:

Code: Select all

; Client
; Example by Pupil 2002/06/21

If InitNetwork() = 0
  Debug "Initnetwork failed!"
  End
EndIf

server.s = "127.0.0.1"
port.l = 5555

If OpenWindow(0, 100, 100, 300, 100, #PB_Window_SystemMenu, "client") = 0
  Debug "OpenWindow failed!"
  End
EndIf
 
If CreateGadgetList(WindowID(0))
  ButtonGadget(0, 5,5, 100, 20, "Connect")
  ButtonGadget(1, 5, 30, 100, 20, "Send data")
  ButtonGadget(2, 5, 55, 100, 20, "Disconnect")
  DisableGadget(1, 1)
  DisableGadget(2, 1)
Else
  Debug "Couldn't create gadgets!"
  End
EndIf

Repeat
  event.l = WaitWindowEvent()
    
  Select event
    Case #PB_EventGadget
      Select EventGadgetID()
        Case 0
          clientid.l = OpenNetworkConnection(server, port)
          If clientid
            DisableGadget(0, 1)
            DisableGadget(1, 0)
            DisableGadget(2, 0)
          EndIf
        Case 1
          For i=0 To 100
            sendmsg.s = "This data is sent over the networkconnection 101 times "
            sendmsg + "and should be received by the server intact. This is message number "+Str(i)+"."+Chr(13)+Chr(10)
            SendNetworkData(clientid, @sendmsg, Len(sendmsg))
          Next
        Case 2
          CloseNetworkConnection(clientid)
          DisableGadget(0, 0)
          DisableGadget(1, 1)
          DisableGadget(2, 1)
      EndSelect
    Case #PB_EventCloseWindow
      quit = 1
  EndSelect
Until quit
  
Hope you'll have some help from them. Worked OK on w2k.

Edited
Maybe i missunderstood you, let's get this straight. Correct me if i'm wrong, you wanted to as a client initiate a two way comunication with a server i.e. first you send a request and then wait for the answer from the server? If this is the case i missunderstood you and my code will be totally useless... Well some small alterations to the client and server and it wouldn't be all useless.




Edited by - Pupil on 21 June 2002 19:23:30
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by TerryHough.
Hope you'll have some help from them. Worked OK on w2k.
Your example of sending data via the PB Network commands is a
great help.

I actually need to send files. Haven't got a short example of
that laying around you would share, have you?

I need to do an unattended client program that accesses a server
to exchange files (upload and download). Server needs to validate
client ID, and then allow the client to upload and download multiple
files in defined directories per client. There are usually
several files to upload and download, and I hope to have a progress
bar to keep the user informed.

Thanks again for your example, and any other advice you can provide.

Terry
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Pupil.
Hope you'll have some help from them. Worked OK on w2k.
Your example of sending data via the PB Network commands is a
great help.

I actually need to send files. Haven't got a short example of
that laying around you would share, have you?

I need to do an unattended client program that accesses a server
to exchange files (upload and download). Server needs to validate
client ID, and then allow the client to upload and download multiple
files in defined directories per client. There are usually
several files to upload and download, and I hope to have a progress
bar to keep the user informed.

Thanks again for your example, and any other advice you can provide.

Terry
Unfortunately i haven't got an off the shelf ready program to present to you but from what i understand from your post you need to set up some sort of handshaking procedure between client and server that enables the client to be authenticated. This means that on the server side you must put the clients that connect in different states i.e. unauthenticated and authenticated, you probably need some more states between those two. This can be done by allocating a structure (preferably a linked list) for each connection that is made, and in this structure have a variable that holds the actual state of the client assigned to that particular element. perhaps you can look at the Atomic FTP server program that is located on the PureBasic site (under download i think) to get some inspiration when it comes to handshaking and such.

When sending a file, you probably don't want to load the entire file into memory so you have to load it in chunks and send it in chunks. This not only saves memory but also makes it easier to implement the progressbar, as you can update it as soon as you have sent away a chunk of data.

Sorry i couldn't provide you with some example code instead of just some thoughts put into words.

BTW, you could check out the excellent Chat app. that Paul has put together, you can find it on the PB resource site. It's called "PB Chat" if i'm not totally wrong.
http://www.reelmediaproductions.com/pb/
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by TerryHough.
When sending a file, you probably don't want to load the entire file into memory so you have to load it in chunks and send it in chunks. This not only saves memory but also makes it easier to implement the progressbar, as you can update it as soon as you have sent away a chunk of data.
Thanks for responding. I will let the ideas "ferment" for awhile and see
what I can come up with. I will also review the examples you mentioned.

Anyway, your code got me started with the idea and will be a big help.

Terry
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by TerryHough.

Pupil,

I have had a go at it, and have about 75% of
it working as desired thanks to your code.

Server now:
1) Accepts data per your example (not needed for my app)
2) Accepts files sent using ReceiveNetworkFile
3) Accepts files send in chunks using ReceiveNetworkData
with a progress bar integrated.
4) Responds to client request to download a file and sends
it in chunks with a progress bar integrated.
5) Accepts USER ID and PASSWORD for future validation routine.

Client now:
1) Sends data per your example (not needed for my app) but
left in for learning.
2) Sends USER ID and PASSWORD to server for future validation routine
3) Selects and sends a file upload request (PUT) to server and then sends
the file using SendNetworkFile.
4) Selects and sends a file upload request (PUT) to server and then sends
the file in chunks using SendNetworkData with a progress
bar integrated.
5) Sends a file download request to the server (GET) and waits to
receive the file (not working quite yet)

I will post some well commented code when finished with my thanks for your
help. Unfortunately, work schedule will keep me away from coding for the
next 10 days.

But, not bad so far for someone who had never written a line of PureBasic
code till this week.

Regards,
Terry
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by TerryHough.

As promised, here is your example expanded to exchange files.

First, a word of caution. Use this at your own risk. This is my first effort at PureBasic code. It has been tested only across my own network and timing/delays can be critical for network communications.

If you improve this code or have suggestions for improvment, please let me know.

The ListViews pretty much explain what is going on, and a log is written by both the Client and the Server.

First the Server:

Code: Select all

; ELF_Server
; expanded by Terry Hough - Datagroup Inc. - 08/22/2002
; based on example by Pupil 2002/06/21

Global threadmessage.l, threadanswer.l

Declare NetworkProc(foo.l)

FileName$        = "Received.fle"     ; set a default filename
ReceiveDataMode  = 0                  ; set a default flag 
ReceiveFileMode  = 0                  ; set a default flag - not currently in use
TotReceived      = 0                  ; set a default accumulater to zero
BufLex.l         = 2048               ; set a default buffer length to use

If InitNetwork() = 0
  Debug "Initnetwork failed!"
  End
EndIf

port.l = 5555

If OpenWindow(0, 420, 260, 300, 300, #PB_Window_SystemMenu|#PB_Window_MinimizeGadget, "ELF Server") = 0
  Debug "OpenWindow failed!"
  End
EndIf
 
; Create all the gadgets
If CreateGadgetList(WindowID(0))
  ButtonGadget(0, 5,  5, 100, 20, "Start Server")
  ButtonGadget(1, 5, 30, 100, 20, "Stop Server ")
  DisableGadget(1, 1)
  ListViewGadget(7, 5, 55, 290, 160)
  AddGadgetItem(7, -1, "Network server idle")
  MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
; Created and initialize a prgress bar 
  TextGadget(8, 5,220, 290, 20, "Transmission progress") 
  ProgressBarGadget(9, 5, 240, 290, 20, 0, 100,#PB_ProgressBar_Smooth)
  SetGadgetState(9, 0)    
Else
  Debug "Couldn't create gadgets!"
  End
EndIf
; End gadget creation

Repeat
  event.l = WaitWindowEvent()
    
  Select event
    Case #PB_EventGadget
      Select EventGadgetID()
        Case 0
          If CreateNetworkServer(port)
            DisableGadget(0, 1)
            DisableGadget(1, 0)
            ; Log the server activation
            OpenFile(1, "serverlog.txt") 
            FileSeek(Lof())
            WriteStringN("Network server active and listening")
            CloseFile(1)
            ; End logging the server activation
            AddGadgetItem(7, -1, "Network server active and listening")
            MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
            threadmessage = 0
            CreateThread( @NetworkProc(), 0)
          EndIf
        Case 1
            ; Log the server deactivation
            OpenFile(1, "serverlog.txt") 
            FileSeek(Lof())
            WriteStringN("Network server idle")
            CloseFile(1)
            ; End logging the server deactivation
          ClearGadgetItemList(7) 
          AddGadgetItem(7, -1, "Network server idle")
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
          ; Clear the progress bar 
          TextGadget(8, 5,220, 290, 20, "Transmission progress") 
          SetGadgetState(9, 0)    
          threadmessage = 1
          While threadanswer = 0
            Delay(1)
          Wend
          CloseNetworkServer()
          DisableGadget(0, 0)
          DisableGadget(1, 1)
      EndSelect
    Case #PB_EventCloseWindow
      quit = 1
  EndSelect
Until quit
End

DisableDebugger

Procedure NetworkProc(foo.l)
  threadanswer = 0

  Repeat
    netevent = NetworkServerEvent()
    If netevent
      clientid = NetworkClientID()

      Select netevent
        AddGadgetItem(7, -1, "Netevent: " + Str(netevent))      ; for debugging
        MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)  ; for debugging


        Case 1 ; Client connected
          ReceiveDataMode = 0            ; reset the flag  
          ; Log the client connection
          OpenFile(1, "serverlog.txt")
          FileSeek(Lof())
          WriteStringN("Client "+ Str(clientid) + ": connected")
          CloseFile(1)
          ; End logging the client connection
          AddGadgetItem(7, -1, "Client " + Str(clientid) + "; network client connected")
          AddGadgetItem(7, -1, "Require Client " + Str(clientid) + " to login")
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
          SendNetworkString(clientid, "LOGIN?")

        Case 2 ; Data has been received via the network
          *buffer = AllocateMemory(0, 8192, 0)
          Repeat
            length = ReceiveNetworkData(clientid, *buffer, 8192)
;            AddGadgetItem(7, -1, "Length received: " + Str(length))       ; for debugging
;            Test$=PeekS(*buffer,length)                                   ; for debugging
;            AddGadgetItem(7, -1, "[" + Test$ + "]")                       ; for debugging
;            MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)        ; for debugging

                        
            If length > 0

              ; Check for USER ID arriving  
              If Result = CompareMemoryString(*buffer, "USER ", 1, 5) 
                UserID$ = PeekS(*buffer, length)
                UserID$ = Mid(UserID$,6,Len(UserID$))
                ReceiveDataMode = 0            ; reset the flag  
                ; Log the USER ID request
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client " + Str(clientid) + ": Login requested by: " + UserID$)
                CloseFile(1)
                ; End logging the USER ID request
                AddGadgetItem(7, -1, "Login requested by: " + UserID$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                SendNetworkString(clientid, "USER " + UserID$)
                
              ; Check for PASSWORD arriving
              ElseIf Result = CompareMemoryString(*buffer, "PASS ", 1, 5) 
                PassID$ = PeekS(*buffer, length)
                PassID$ = Mid(PassID$,6,Len(PassID$))
                ReceiveDataMode = 0            ; reset the flag  
                ; Log the PASSWORD request
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": Password supplied: " + PassID$)
                CloseFile(1)
                ; End logging the PASSWORD request
                AddGadgetItem(7, -1, "Password supplied: " + PassID$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                SendNetworkString(clientid, "PASS " + PassID$)
                ; Now that we know USER ID and PASSWORD, authenticated them 
                ;   Call the AUTHENTICATION procedure here
                ;   If access allowed, continue 
                ;   Else disonnect the client
                ; This routine is not yet written

              ; Check for PUT (file upload) request arriving
              ElseIf Result = CompareMemoryString(*buffer, "PUT ", 1, 4) 
                NewFile$ = PeekS(*buffer, length)
                NewFile$ = Mid(NewFile$,5,Len(NewFile$))
                position=FindString(NewFile$," ",1)
                NewFileLength$ = Mid(NewFile$, position + 1, Len(NewFile$)) 
                FileLength=Val(Trim(NewFileLength$))
                TotFileSize = FileLength/100
                TotReceived = 0
                NewFile$ = Mid(NewFile$, 1, position-1)
                ; Log the PUT a file request
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": Upload request: " + NewFile$ + " " + NewFileLength$ + " bytes")
                CloseFile(1)
                ; End logging the PUT request
                FileName$ = NewFile$
                AddGadgetItem(7, -1, "Upload request: " + FileName$ + " " + Str(FileLength) + " bytes")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                SetGadgetText(8, FileName$ + " " + Str(FileLength) + " bytes expected, be patient")
                SetGadgetState(9, 0)  
                OpenFile(0, FileName$)
                ReceiveDataMode = 1         ; turn the receive data mode flag on
                SendNetworkString(clientid, "PUT: " + NewFile$ + " " + Str(FileLength))
                AddGadgetItem(7, -1, "Transfer approved: " + NewFile$ + " " + NewFileLength$ + " bytes")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend

              ; Check for GET (file download as data) request arriving and respond  
              ElseIf Result = CompareMemoryString(*buffer, "GET: ", 1, 5) 
                DownFile$ = PeekS(*buffer, length)
                DownFile$ = Mid(DownFile$,6,Len(DownFile$))
                ReceiveDataMode = 0            ; reset the flag  
                ; Log the GET a file request
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": Download Request: " + DownFile$)
                CloseFile(1)
                ; End logging the request
                AddGadgetItem(7, -1, "Download request: " + DownFile$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                ; Send the file if it exists
                If ReadFile(0, DownFile$)
                  FileLength = Lof()
                  TotFileSize = FileLength/100 
                  TotReceived = 0                ; clear the accumlator 
                  ; Log the found file size
                  OpenFile(1, "serverlog.txt")
                  FileSeek(Lof())
                  WriteStringN("Client "+ Str(clientid) + ": " + "Download request: " + DownFile$ + " " + Str(FileLength) + " byte file found")
                  WriteStringN("Client "+ Str(clientid) + ": " + "Transfer file   : " + DownFile$ + " " + Str(FileLength) + " bytes")
                  CloseFile(1)
                  ; End logging the found file size
                  AddGadgetItem(7, -1, "Download request: " + DownFile$ + " " + Str(FileLength) + " byte file found")
                  MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                  ; Acknowledge to client with file and filesize  
                  SendNetworkString(clientid, "PUT: " + DownFile$ + " " + Str(FileLength))
                  For i =1 To 1000:Delay(1):Next
                  UseFile(0)
                  indexer = 0
                  Repeat
                    If FileLength - indexer > 8192
                      ReadData(*buffer, 8192) 
                      SendNetworkData(clientid, *buffer, 8192)
                      indexer = indexer + 8192
                    Else
                      ReadData(*buffer, FileLength - indexer) 
                      SendNetworkData(clientid, *buffer, FileLength - indexer)
                      indexer = FileLength
                    EndIf 
                    ; reporting of file transfer progress
                    SetGadgetText(8, DownFile$ +": sent " + Str(indexer) + " of " + Str(FileLength) + " bytes") 
                    SetGadgetState(9, Round(indexer/TotFileSize,1))    ; Show progress bar    
                    ; End reporting of file transfer progress  
                  Until indexer >= FileLength
                  ; Log the completion of the file download
                  OpenFile(1, "serverlog.txt")
                  FileSeek(Lof())
                  WriteStringN("Client "+ Str(clientid) + ": Downloaded file: " + DownFile$ + " " + Str(FileLength) + " bytes")
                  CloseFile(1)
                  ; End logging the file download
                  AddGadgetItem(7, -1, "Downloaded file: " + DownFile$ + " " + Str(FileLength) + " bytes")
                  MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                  ; Reset progress bar
                  CloseFile(0)
                EndIf
                FileName$ = DownFile$

              ; Check for RETR (file download) request arriving and respond  
              ElseIf Result = CompareMemoryString(*buffer, "RETR ", 1, 5) 
                DownFile$ = PeekS(*buffer, length)
                DownFile$ = Mid(DownFile$,6,Len(DownFile$))
                ReceiveDataMode = 0            ; reset the flag  
                ; Log the RETR a file request
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": Download Request: " + DownFile$)
                CloseFile(1)
                ; End logging the request
                AddGadgetItem(7, -1, "Download request: " + DownFile$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                ; Send the file if it exists
                If ReadFile(0, DownFile$)
                  FileLength = Lof()
                  TotFileSize = FileLength/100
                  TotReceived = 0                ; clear the accumlator 
                  CloseFile(0)
                  ; Log the found file size
                  OpenFile(1, "serverlog.txt")
                  FileSeek(Lof())
                  WriteStringN("Client "+ Str(clientid) + ": " + "Download request: " + DownFile$ + " " + Str(FileLength) + " byte file found")
                  CloseFile(1)
                  ; End logging the found file size
                  AddGadgetItem(7, -1, "Download request: " + DownFile$ + " " + Str(FileLength) + " byte file found")
                  MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                  ; Acknowledge to client with file and filesize  
                  SendNetworkData(clientid, "RETR " + DownFile$ + " " + Str(FileLength), Len(DownFile$) + 6 +Len(Str(FileLength)))
                  For i =1 To 1000:Delay(1):Next
                  SendNetworkFile(clientid, DownFile$)
                  ; reporting of file transfer progress
                  SetGadgetText(8, DownFile$ +": sent " + Str(FileLength) + " of " + Str(FileLength) + " bytes") 
                  SetGadgetState(9, Round(FileLength/FileLength*100,1))    ; Show progress bar    
                  ; End reporting of file transfer progress  
                  ; Log the completion of the file download
                  OpenFile(1, "serverlog.txt")
                  FileSeek(Lof())
                  WriteStringN("Client "+ Str(clientid) + ": Downloaded file: " + DownFile$ + " " +Str(FileLength) + " bytes")
                  CloseFile(1)
                  ; End logging the file download
                  AddGadgetItem(7, -1, "Downloaded file: " + DownFile$ + " " +Str(FileLength) + " bytes")
                  MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                  ; Reset progress bar
                EndIf
                FileName$ = DownFile$

              ; Report an ACK message from the server
              ElseIf Result = CompareMemoryString(*buffer, "ACK: ", 1, 5) 
                ACK$ = PeekS(*buffer,length)
                OpenFile(1, "serverlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": " + ACK$)
                CloseFile(1)
                AddGadgetItem(7, -1, ACK$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend

              ; Then it has to be data, so receive it to the designated filename.
              Else  
                UseFile(0)                           ; insure correct file is still selected
                WriteData(*buffer, length)           ; write received data to file 
                TotReceived = TotReceived + length   ; accumulate received length 
                SetGadgetText(8, FileName$ + " - received " + Str(TotReceived) + " of " + Str(FileLength) + " bytes ")
                SetGadgetState(9, Round(TotReceived/TotFileSize,1))    ; Show progress bar    
              EndIf             
            EndIf

          Until length  8192
                ReadData(*buffer, 8192) 
                SendNetworkData(clientid, *buffer, 8192)
                indexer = indexer + 8192
              Else
                ReadData(*buffer, FileLength - indexer) 
                SendNetworkData(clientid, *buffer, FileLength - indexer)
                indexer = FileLength
              EndIf 
              ; Report the data transmission on the client window
              SetGadgetText(8, NewFile$ +": " + Str(indexer) + " of " + Str(FileLength) + " bytes") 
              SetGadgetState(9, Round(indexer/TotFileSize,1))    ; Show progress bar    
              ; End reporting of data transmission  
            Until indexer >= FileLength
            AddGadgetItem(7, -1, "Uploaded: " + NewFile$ + " " + Str(FileLength) + " bytes")
            MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
            While WindowEvent():Wend
            CloseFile(0)
          EndIf
          
        Case 4     ; Disconnect client from the network
          DisableGadget(0, 0)
          DisableGadget(1, 1)
          DisableGadget(2, 1)
          DisableGadget(3, 1)
          DisableGadget(4, 0)
          DisableGadget(5, 1)
          CloseNetworkConnection(clientid)
          SetGadgetText(8, "Transmission progress") 
          SetGadgetState(9, 0)  
          AddGadgetItem(7, -1, "Disconnected from server")
          KillThread(threadid)
          AddGadgetItem(7, -1, "Communication thread discontinued")
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
          ; Log the disconnection request
          OpenFile(1, "clientlog.txt")
          FileSeek(Lof())
          WriteStringN("Client "+ Str(clientid) + ": Disconnected from server")
          WriteStringN("Client "+ Str(clientid) + ": Communciation thread discontinued")
          CloseFile(1)
          ; End logging the request
          LOG_flag=0
          UID_flag=0
          PWD_flag=0


        Case 5    ; Get a file as data from the network server
          SetGadgetText(8, "Transmission progress") 
          SetGadgetState(9, 0)  
          *recvbuffer = AllocateMemory(0, 8192, 0)
          ActivateGadget(6)
;          FileName$ = Trim(GetGadgetText(#6)) 
          FileName$ = "ELFBrowser.exe"
          If FileSize(FileName$) > -1
            response = MessageRequester("ELF File Transfer", FileName$ + " already exists." + Chr(13) + Chr(10) + "Do you want To delete it?", #PB_MessageRequester_YesNoCancel) 
            If response = 6       
              If DeleteFile(FileName$) = -1
                MessageRequester("ELF File Transfer", FileName$ + " cannot be deleted!" + Str(response), #PB_MessageRequester_Ok) 
                FakeEndSelect
                Goto Select_Loop
              EndIf
            ElseIf response = 7
              MessageRequester("ELF File Transfer", FileName$ + " will not be deleted!" + Str(response), #PB_MessageRequester_Ok)
              FakeEndSelect
              Goto Select_Loop
            ElseIf response = 2
              FakeEndSelect
              Goto Select_Loop
            EndIf
          EndIf
          SetGadgetText(8, FileName$ +": requesting download") 
          AddGadgetItem(7, -1, "Request to download file: " + FileName$)
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
          ; Send the server a GET request with filename and size
          SendNetworkString(clientid, "GET: " + FileName$)
          AddGadgetItem(7, -1, "Sent a GET: " + Filename$)
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                    
        Case 10 ; RETR a file via the network
            ; FileName$ and expected length was passed by a RETR request as data
          ActivateGadget(6)
;          FileName$ = Trim(GetGadgetText(#6)) 
          FileName$ = "ELFBrowser.exe"
          If FileSize(FileName$) > -1
            response = MessageRequester("ELF File Transfer", FileName$ + " already exists." + Chr(13) + Chr(10) + "Do you want To delete it?", #PB_MessageRequester_YesNoCancel) 
            If response = 6       
              If DeleteFile(FileName$) = -1
                MessageRequester("ELF File Transfer", FileName$ + " cannot be deleted!" + Str(response), #PB_MessageRequester_Ok) 
                FakeEndSelect
                Goto Select_Loop
              EndIf
            ElseIf response = 7
              MessageRequester("ELF File Transfer", FileName$ + " will not be deleted!" + Str(response), #PB_MessageRequester_Ok)
              FakeEndSelect
              Goto Select_Loop
            ElseIf response = 2
              FakeEndSelect
              Goto Select_Loop
            EndIf
          EndIf
          SetGadgetText(8, FileName$ +": requesting download") 
          AddGadgetItem(7, -1, "Request to download file: " + FileName$)
          MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
          ; Send the server a RETR request with filename and size
          SendNetworkString(clientid, "RETR " + FileName$)
          SetGadgetText(8, FileName$ + " ??? bytes expected, be patient")
          

      EndSelect

    Case #PB_EventCloseWindow
      quit = 1
  EndSelect

Until quit

Procedure NetworkProc(foo.l)
  threadanswer = 0
  loop = 0
  length = 0
  netevent = 0
  
  Repeat
    netevent = NetworkClientEvent(clientid)
    If netevent

      Select netevent
        AddGadgetItem(7, -1, "Netevent: " + Str(netevent))   ; for debugging


        Case 2 ; Data has been received via the network
          *recvbuffer = AllocateMemory(0, 8192, 0)

          Repeat
            length = ReceiveNetworkData(clientid, *recvbuffer, 8192)
            If length > 0
;               AddGadgetItem(7, -1, "Length received: " + Str(length))       ; for debugging
;               Test$=""                                                      ; for debugging 
;               Test$=PeekS(*recvbuffer,50)                                   ; for debugging
;               AddGadgetItem(7, -1, "[" + Test$ + "]")                       ; for debugging
;               While WindowEvent():Wend

              ; Check for connection acknowledged by server  
              If Result = CompareMemoryString(*recvbuffer, "LOGIN?", 1, 6) 
                OpenFile(1, "clientlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": Login required by server")
                WriteStringN("Client "+ Str(clientid) + ": Sending USER ID")
                CloseFile(1)
                AddGadgetItem(7, -1, "Login required by server")
                AddGadgetItem(7, -1, "Sending USER ID")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend
                SendNetworkData(clientid, "USER " + UserName$, Len(UserName$) + 5)
                LOG_flag = 1

              ; Check for USER ID acknowledged by server  
              ElseIf Result = CompareMemoryString(*recvbuffer, "USER ", 1, 5) 
                UserID$ = PeekS(*recvbuffer, length)
                UserID$ = Mid(UserID$,6,Len(UserID$))
                UID_flag = 1
                OpenFile(1, "clientlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": " + UserID$ + " -  received at server")
                WriteStringN("Client "+ Str(clientid) + ": Sending PASSWORD")
                CloseFile(1)
                AddGadgetItem(7, -1, UserID$ + " - received at server")
                AddGadgetItem(7, -1, "Sending PASSWORD")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend
                SendNetworkData(clientid, "PASS " + PassWord$, Len(PassWord$) + 5)

              ; Check for PASSWORD acknowledged by server
              ElseIf Result = CompareMemoryString(*recvbuffer, "PASS ", 1, 5) 
                PassID$ = PeekS(*recvbuffer, length)
                PassID$ = Mid(PassID$,6,Len(PassID$))
                PWD_flag = 1
                OpenFile(1, "clientlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": " + PassID$ + " - password received at server")
                CloseFile(1)
                AddGadgetItem(7, -1, PassID$ + " - received at server")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend

              ; Report an ACK message from the server
              ElseIf Result = CompareMemoryString(*recvbuffer, "ACK: ", 1, 5) 
                ACK$ = PeekS(*recvbuffer,length)
                OpenFile(1, "clientlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": " + ACK$)
                CloseFile(1)
                AddGadgetItem(7, -1, ACK$)
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend

              ; Check for GET (file download as data) acknowledged by server with a PUT
              ElseIf Result = CompareMemoryString(*recvbuffer, "PUT: ", 1, 5) 
                NewFile$ = PeekS(*recvbuffer, length)
                NewFile$ = Mid(NewFile$,6,Len(NewFile$))
                position=FindString(NewFile$," ",1)
                NewFileLength$ = Mid(NewFile$, position + 1, Len(NewFile$))
                FileLength = Val(NewFileLength$)
                TotFileSize = FileLength/100
                TotReceived = 0 
                FileName$ = Mid(NewFile$, 1, position-1)
                ; Log the put a file request
                OpenFile(1, "clientlog.txt")
                FileSeek(Lof())
                WriteStringN("Client "+ Str(clientid) + ": " + FileName$ + " - put requested - " + NewFileLength$ + " bytes")
                CloseFile(1)
                ; End logging the request
                AddGadgetItem(7, -1, FileName$ + " - put requested - " + NewFileLength$ + " bytes")
                MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
                While WindowEvent():Wend
                ; See if the file already exists
                oldlength = FileSize(FileName$)
                AddGadgetItem(7, -1, "Filesize of " + FileName$ + " " + Str(oldlength) + " found")  ; debugging remove later
                If oldlength  -1
;                  If DeleteFile(FileName$) = 0
;                    MessageRequester("ELF File Transfer", FileName$ + " cannot be deleted!" + Str(response), #PB_MessageRequester_Ok) 
;                    FakeEndSelect
;                    Goto Select_Loop
;                  EndIf
;                EndIf


              Else
                UseFile(0)                           ; insure correct file is still selected
                WriteData(*recvbuffer, length)       ; write received data to file 
                TotReceived = TotReceived + length   ; accumulate received length 
                SetGadgetText(8, FileName$ + " - received " + Str(TotReceived) + " of " + Str(FileLength) + " bytes ")
                SetGadgetState(9, Round(TotReceived/TotFileSize,1))    ; Show progress bar    
              EndIf
              length = 0             
            EndIf
          length = 0
          
          Until length < 1
          If ReceiveDataMode              ; Is a file receive active?  
            If TotReceived = FileLength     ; has entire expected filelength been received?
              CloseFile(0)                  ; close the file
              ReceiveDataMode = 0           ; reset the flag set by PUT request 
              ; Log the completion of the data download
              OpenFile(1, "clientlog.txt") 
              FileSeek(Lof())
              WriteStringN("Client "+ Str(clientid) + ": Received file: " + FileName$ + " " + Str(TotReceived) + " bytes")
              CloseFile(1)
              ; End logging the download results
              AddGadgetItem(7, -1, "Received file: " + FileName$ + " " +Str(TotReceived) + " bytes")
              MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
              ; ACKnowledge the successful receipt of the file back to the client
              SendNetworkString(clientid, "ACK: " + FileName$ + " " +Str(TotReceived) + " bytes")
              AddGadgetItem(7, -1, "ACK: Received " + FileName$ + " " +Str(TotReceived) + " bytes")
              MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
              While WindowEvent():Wend
            EndIf                         ; if so, close file and log it
          EndIf                         ; If not, wait For more Data  


        Case 3 ; A file has been received via the network
            ReceiveNetworkFile(clientid, FileName$)
            If ReadFile(0,FileName$)
              FileLength = Lof()
              CloseFile(0)
            EndIf    
            OpenFile(1, "clientlog.txt")
            FileSeek(Lof())
            WriteStringN("Client "+ Str(clientid) + ": " + FileName$ + " - " + Str(FileLength) + " bytes received")
            CloseFile(1)
            AddGadgetItem(7, -1, "File received: " + FileName$ + " - " + Str(FileLength) + " bytes") 
            MoveToEnd = SetGadgetState(7, CountGadgetItems(7) - 1)
            While WindowEvent():Wend
            SetGadgetText(8, FileName$ + ": received " + Str(FileLength) + " of " + Str(FileLength) + " bytes ")
            SetGadgetState(9, Round(FileLength/FileLength*100,1))    ; Show progress bar    
            ; ACKnowledge the successful receipt of the file back to the client
            SendNetworkString(clientid, "ACK: " + FileName$ + " " +Str(FileLength) + " bytes")
      EndSelect

    Else
      Delay(1)
    EndIf

  Until threadmessage
  threadanswer = 1

EndProcedure
Enjoy, but don't laugh at my coding style to hard...
Terry
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Franco.

Hi Terry,
just had a bit time and tested your code.

I tested it under Win2k-Sp3 so the problems could arise with the OS (Server & Client on one machine).
Found 2 strange behaviour and 1 bug:

Under 'Send file' and 'Send file as data' the original file changes the size to 0 byte after sending.
The copy (the sent one) of this file has the correct file size (tested with a 7MB file).
A 'Send' command should not destroy the original file...

'Get file as data' is buggy; the received bytes are smaller than the original one.

'Get file' seems to work correctly.

Didn't found out what 'Send data' should do though, nothing happens...

Conclusion: Sweet first piece of code...
Keep coding

BTW: Thanks to Pupil for the initial work :)

Have a nice day...
Franco

Sometimes you have to go a lonely way to accomplish genius things.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by TerryHough.
Originally posted by Franco
Under 'Send file' and 'Send file as data' the original file changes the size to 0 byte after sending.
The copy (the sent one) of this file has the correct file size (tested with a 7MB file).
A 'Send' command should not destroy the original file...
Actually, the sent file is not destroyed, but the ListView reporting in the Client has a bug in it that reports the file as 0 bytes. Seems to have crept in over the last two days.

There is also a problem sending the same file twice in a row. It works but then gives an error messge occasionally. Not everytime, but fairly repeatable. Is there an emoticon for "beating your head on the desk"?

'Get file as data' is buggy; the received bytes are smaller than the original one.
Not here locally on Win98SE. I have used several files, exe, and zips. All came over intact. However, the delays necessary to have the "network settle" are touchy. I have had to play with it quite a bit. A little more handshaking code may be required.

'Get file' seems to work correctly.

Didn't found out what 'Send data' should do though, nothing happens...
Just sends some ASCII data. No real use for it, but held it over from Pupil's example.

Conclusion: Sweet first piece of code...
Keep coding
Thanks, it was an interesting exercise and I learned quite a bit. Hopefully I will get a chance to improve this pair of programs and repost them later. I am already coding on using the concept to solve the problem that led me to this example to begin with.
s you have to go a lonely way to accomplish genius things.

Terry
Post Reply