FTP from Windows CE 5.0 Devices






4.75/5 (8 votes)
Windows CE devices are not setup properly for the use of FTP despite the HttpWebRequest and HttpWebResponse classes.
Introduction
In the industry, many hand-held devices with bar code scanners are still in use. With Windows CE 5.0, it is possible to program applications for these devices, who's technology was 10 years ago mainstream. One of my clients is using these devices to scan bar codes outside his buildings. While registering his data in SQL Compact, he does not want to use the sync framework to get his data in the central system. He uses FTP. And FTP is not so well supported in the Compact .NET Framework. Microsoft offers a solution to use HttpWebRequest
to send the file to the central system. But that NAS replies me with '405 Method not Allowed'. After that, I used the OpenNet CF DLLs to use FtpRequest
. It looked like the file was sent, but no data was received on the NAS. Despite the log files, no errors were found. After these pitfalls, I decided to use a TcpClient
to send the files. And that works like a charm. In this article, only BASIC sending with FTP is described. Please read the comments in the source code.
One other thing. Visual Studio 2008 was the latest version to be able to create such mobile applications. There are possibilities in VS 2013 but I do not have a license for that (yet).
Background
The TcpClient
allows you to create connections to other client over the TCP/IP protocol. In that case, you can make your own FTP client to send files. A low level solution that works, but FTP must be known by the programmer. In fact, it is a question/answer system. Furthermore the Compact Framework supports:
event Action<someObject> SomeEventAFormCanSubScribeToEvent;
So an interface can describe the event and can be shot via the class and the form only needs the received object to update its form objects.
Due to limitations of the Compact Framework 2.0, FTP is not so well incorporated in the Framework as is in the newer Frameworks. By writing FTP possibilities in your code, you can achieve sending of files.
Using the Code
When you use this code, you are able to connect to an FTP Server and send a file to it. You can set up connection with 'User name' and 'Password', but you can also comment out these lines. In the program, a check is done if your device can connect to the PPP_Peer protocol, otherwise you cannot reach an FTP server.
Getting Started
In this example, a simple form holds:
Label
with text "File Progress"ProgressBar
which shows how many files have been sentLabel
with response from the FTP ServerLabel
with text "Files"ListBox
which will show the file names ready to be sent. TheListBox
isReadOnly
. While transferring files, the transferred file is selected in the list.Button
with text "Start
". If theListBox
contains more than 0 lines and PPP_Peer can be found, the button is Enabled.Instantiates the interface IFtpClient
and uses the available commands to transfer files and get event updates from the files.
The form listens to the next events.
FtpProgressEvent
: holds anFtpProgress
business object with data of the current transferring file.RetrieveFileListEvent
: Gets aFileInfo[]
object with files that can be sent.SendFinishedEvent
: Receives aString
message to show in a message-box after all files have been transferred.
The class FtpClient
uses class FTPHelper
and interface IFtpClient
. In class FtpClient
, you will find 3 methods:
public GetLocalFiles
: This sets aFileInfo[]
object with the available files and shoots theRetrieveFileListEvent
event.public SendFiles()
: Methods to send the files in theFileInfo[]
object.private FtpClient_FtpCurrentProgressEvent(
. This method listens to theFtpProgress
ftpProgress)FtpCurrentProgressEvent
inFTPHelper
class; The event is set in the constructor of theFtpClient
class. This methods sets theFtpProgressEvent
so the form updates its controls.
There is 1 read only property in the class called ActiveSyncConnectionEnabled
. This property can tell if the device can connect to the FTP server via FTPHelper
class Boolean
ActiveSyncConnected
.
In class FTPHelper
, you will find 5 methods:
SendFTPCommand(
: writes the command with needed verb(s) to theString
Command,String
Verb,String
Verb2)StreamWriter
CreatePassiveFtpSocketInformation()
: when sending a file, the PASV command is used. The response gives astring
that must be converted to anIPEndPoint
with a port number.ReadLineFromStream()
: After writing a command to theStreamWriter
, read the response stream. This response is send to theFtpCurrentProgressEvent
event.ReadAllBytesFromTheFile(
: Read the bytes from the file that will be sent to the FTP server.FileInfo
file)StartCurrentProgressEvent()
: Method to send the currentFtpProgress
business object to the form viaFtpClient
class.
Business Objects
There are 2 business objects in the source files:
FtpPassiveConnection
: which holds the passive IP address and the passive port number:public IPAddress PassiveIP; public Int32 PasssivePortNr;
FtpProgress
: which holds information about the current file in transfer and information for theProgressBar
:public Int32 CurrentFileNr; // after sending each file Iterate +1. The selectedIndex of the ListBox will reflect the current file in sending public Int32 LastFileNr; // needed for the Maximum property for the ProgressBar public String FileName; // name of the current file name public Int64 FileBytes; // the number of bytes to be send. When streaming in parts a file progress can be shown (2nd progress bar needed) public Int64 SendFileBytes; // number of bytes send public String FtpResponse; // current FtpReponse
There is 1 helper class called IOHelpers
and fills the FileInfo[]
object in the application.
There is 1 class for basic exception handling ExceptionHandling.ShowMessage
. It shows a MessageBox
with the occurred exception.
Basic Information on TcpClient
When using the TcpClient
for the Compact Framework, you'll notice no difference with that of the 2.0 framework. See here. You can easily use the TcpClient
class by stating:
TcpClient client = new TcpClient();
// in this case the next line will be
client.Connect(servername, port); // servername = String, port is Int32
or:
TcpClient client = new TcpClient(servername, port); // servername = String, port is Int32
Note that you can also connect by using an IPEndPoint
. See here.
TcpClient
uses IDisposable
so it is advised to use:
using (TcpClient client = new TcpClient(servername, port))
{
// code here
}
Basic FTP Knowledge
Some FTPServers
have welcoming messages of more than 1 line. So when only reading 1 line, the client starts running behind the truth. FileZille server has 3 lines in the welcoming message. But how to detect in FTP answers if you are dealing with multiple lines or not. The answer of an FTP server always start with 3 digits. After these 3 digits, you see a - or a <space>. When you see the space, you know you are on the last line of the server's answer. In code:
protected void ReadLineFromStream()
{
bool MultipleLines = false;
while (true)
{
string line = rdStrm.ReadLine();
MultipleLines = line.Substring(3, 1).Equals("-");
ftpProg.FtpResponse = line;
StartCurrentProgressEvent();
if (!MultipleLines) break;
}
}
Points of Interest
The TcpClient
is useful with older communication technologies that are still used today.
History
- 15th April, 2014
- Initial article
- 25th April, 2014
- Fixed
NULL
reference exception - Reading all lines from the
stream
instead of one
- Fixed
- 30th April, 2015
- Solved the
Control.Invoke
exception caused by using a thread to start the FTP sending of files. It is now non-threaded created.
- Solved the