Android Tutorial [B4X] FTP Server implemented with Socket and AsyncStreams

Discussion in 'Tutorials & Examples' started by Erel, Dec 19, 2016.

  1. Erel

    Erel Administrator Staff Member Licensed User

    [​IMG]
    (Note that the FTP client above is not part of this solution. It only demonstrates how you can use a standard FTP client to communicate with the server.)

    This is an example of using low level network features to implement a high level protocol.
    It is an implementation of a standard FTP server. You can use standard FTP client programs to send or receive files.
    As it is based on AsyncStreams and it can handle multiple concurrent connections.
    It is compatible with B4J, B4i and B4A.
    Note that only passive mode (which is the preferred method) is implemented.

    It is a good example of using classes to handle multiple clients.
    The solution is made of three classes:
    FTPServer - There is a single instance of this class. It manages the server socket that listens on the control port (main port).
    It also manages the connected clients and assigns a data port for each client.

    FTPClient
    - There is an instance of this class for each active connection. It uses AsyncStreamsText class to read the clients text commands. It creates a new FTPDataConnection instance for each task that requires communication over the data socket (upload, download and list files).

    FTPDataConnection - An instance is created for each data task. It sends or receives the data and then closes the connection. Note that a new method was added to AsyncStreams that allows closing the channel after the data was sent (SendAllAndClose). Clients expect the data socket to be closed after the data is sent. There isn't any other cue that tells the client that all data was sent.

    Not all commands are implemented. The common feature are supported: upload, download, delete, rename, list and others.

    In B4A and B4J, JavaObject is used to call a native API that gets the canonical path and verify that the path is inside the set directory. There is no equivalent API in iOS. It is less important as each app is sandboxed anyway.

    Using the server is simple:
    Code:
    server.Initialize(Main, "FTPServer")
    server.SetPorts(510415104251142)
    server.AddUser("Test""test"'user name and password.
    server.BaseDir = File.DirRootExternal
    server.Start
    SetPorts - Sets the control port and the range of available data ports. When running on a non-mobile device, you need to make sure that the firewall allows incoming connections on all these ports.
    AddUser - Adds a user name and password. You can call it multiple times.
    BaseDir - Sets the client root folder.

    In B4i you also need to stop the server when the application moves to the background and start it again when it resumes.

    Implementing an FTP server that properly supports multiple clients is not a simple task. The code itself is not too complicated and is recommended for anyone who is working with network sockets.


    Make sure to copy the libraries to the internal libraries folder (check your current version first).

    [​IMG]

    The most updated classes are in the B4J project. The classes are cross platform compatible. You should add the classes from the B4J project to your project.
     

    Attached Files:

    Last edited: Sep 12, 2017
  2. Douglas Farias

    Douglas Farias Expert Licensed User

    wow, erel is a genius.
     
    jinyistudio and Artigala like this.
  3. coslad

    coslad Well-Known Member Licensed User

    How to change the server adress from WIFI to Ethernet .
    I have an adroid box tv, i use it as a sever , it has an ethernet connection and the wifi is off , the server's example uses the wifi connection , some suggest how to switch to ethernet ?
     
  4. Erel

    Erel Administrator Staff Member Licensed User

    You don't need to do anything special. The ServerSocket should listen on both the ethernet connection and the wifi connection.
     
  5. coslad

    coslad Well-Known Member Licensed User

    You are right, it listens even at Ethernet port, instead b4a bridge not does it, my mistake borned from that.
     
  6. Erel

    Erel Administrator Staff Member Licensed User

    B4A-Bridge also listens on all available networks.
     
  7. TomDuncan

    TomDuncan Active Member Licensed User

    Have setup an FtpServer and all works ok (in release mode, not debug mode)
    If I use Filezilla transfers are fine.
    However, my ip-camera will not work.
    I have it working using a Filezilla Server.
    Here is the log files for an image transfer..

    Code:
    (000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> Connected, sending welcome message...
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> 220-FileZilla Server version 0.9.41 beta
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> 220-written by Tim Kosse (Tim.Kosse@gmx.de)
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> 220 Please visit http://sourceforge.net/projects/filezilla/
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> USER point
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> 331 Password required for point
    (
    000105)4/05/2017 13:38:23 PM - (not logged in) (10.1.1.20)> PASS ********
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 230 Logged on
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> TYPE I
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 200 Type set to I
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> CWD /20170504/images/
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 250 CWD successful. "/20170504/images" is current directory.
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> PASV
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 227 Entering Passive Mode (10,1,1,39,230,116)
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> STOR P17050413383710.jpg
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 150 Connection accepted
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 226 Transfer OK
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> QUIT
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> 221 Goodbye
    (
    000105)4/05/2017 13:38:23 PM - point (10.1.1.20)> disconnected
    Is something not setup with the B4J FTPServer?

    Tom
     
  8. Erel

    Erel Administrator Staff Member Licensed User

    Can you post the logs from the FTP server when the IP camera uploads a file?
     
  9. TomDuncan

    TomDuncan Active Member Licensed User

    Here are the log files.
    1st one is from Filezilla to prove it works.
    Copied a doc file
    2nd one is from the ip-camera doing a test.
    Sets up a folder (date) then 'images'
    ..

    Code:
    Number of clients: 1
    client: AUTH TLS
    client: AUTH SSL
    client: USER xxx
    client: PASS xxx
    User logged 
    in: xxx
    client: PWD
    Number of clients: 
    2
    client: AUTH TLS
    client: AUTH SSL
    client: USER xxx
    client: PASS xxx
    User logged 
    in: xxx
    client: CWD /
    CurrentPath: /
    client: PWD
    client: 
    TYPE I
    client: PASV
    client: STOR patient_update.doc
    Data connection terminated: /patient_update.doc
    client: PASV
    client: 
    LIST
    Data connection terminated: /
    terminated
    Number of clients: 
    1
    Number of clients: 
    2
    client: USER xxx
    client: PASS xxx
    User logged 
    in: xxx
    client: 
    TYPE I
    client: CWD /
    20170505/images/
    client: QUIT
    Number of clients: 
    1
     
  10. Erel

    Erel Administrator Staff Member Licensed User

    The FTP server only works in passive mode. Make sure that the ip camera is set in passive mode.

    Check whether the camera sends the PASV command (not sure from the above logs whether it was the camera or the Filezilla client).
     
  11. TomDuncan

    TomDuncan Active Member Licensed User

    Here is a log from Filezilla Server..

    Code:
    (003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> Connected, sending welcome message...
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> 220-FileZilla Server version 0.9.41 beta
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> 220-written by Tim Kosse (Tim.Kosse@gmx.de)
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> 220 Please visit http://sourceforge.net/projects/filezilla/
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> USER point
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> 331 Password required for point
    (
    003348)5/05/2017 19:35:03 PM - (not logged in) (10.1.1.20)> PASS ********
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 230 Logged on
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> TYPE I
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 200 Type set to I
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> CWD /20170505/images/
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 250 CWD successful. "/20170505/images" is current directory.
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> PASV
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 227 Entering Passive Mode (10,1,1,39,201,255)
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> STOR P17050519352310.jpg
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 150 Connection accepted
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 226 Transfer OK
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> QUIT
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> 221 Goodbye
    (
    003348)5/05/2017 19:35:03 PM - point (10.1.1.20)> disconnected.
    and yes the ipcamera does send a PASV command.
     
  12. Erel

    Erel Administrator Staff Member Licensed User

    Put a breakpoint in ChangeDir sub and see what happens when the camera tries to change the directory (CWD).
     
  13. TomDuncan

    TomDuncan Active Member Licensed User

    Put the breakpoint in.
    Seems as though the directory on the server is not created.
    The FileExists returns false.
     
  14. Erel

    Erel Administrator Staff Member Licensed User

    CWD only changes the directory. It doesn't create one. Try to create it and see whether it works.
     
  15. OliverA

    OliverA Well-Known Member Licensed User

    Looks like the response code of 200 for CWD may be the issue. FileZilla returns 250, the B4J implementation returns 200. If you look at the RFC (https://www.ietf.org/rfc/rfc959.txt), the reply codes for CWD are:
    This site (https://cr.yp.to/ftp/cwd.html) does mention that 200 may be returned, but that 250 is a requirement.
     
  16. RichardHirst

    RichardHirst Member Licensed User

    Hello Erel, Great work on the Server.

    Do you have any way of seeing the Data arrive at the Server End. Is there a "FTP_DownloadProgress" event as in the FTP Client.

    Also does the Server support resume..?

    Thank You

    Richard
     
  17. Erel

    Erel Administrator Staff Member Licensed User

    The data is written to the file in FTPDataConnection AStream_NewData. You can add a counter there and monitor the progress.

    Resume is not implemented (it should probably not be too difficult to implement it, see the code in FTPDataConnection).
     
  18. aidymp

    aidymp Active Member Licensed User

    Hi,
    I use this in a few apps, but now I want to have an option of when the app starts the server is not running, until i turn the feature on, and also would like to be able to turn it off. However It appears that I cannot get it to run out side the starter service? How can I achieve the above?

    Thanks

    Aidy
     
  19. Erel

    Erel Administrator Staff Member Licensed User

    aidymp and Rantor777 like this.
  20. HAH

    HAH Active Member Licensed User

    Is this possible:

    Code:
    server.BaseDir = File.DirInternal
     
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice