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 sent
Label
with response from the FTP Server
Label
with text "Files"
ListBox
which will show the file names ready to be sent. The ListBox
is ReadOnly
. While transferring files, the transferred file is selected in the list.
Button
with text "Start
". If the ListBox
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 an FtpProgress
business object with data of the current transferring file.
RetrieveFileListEvent
: Gets a FileInfo[]
object with files that can be sent.
SendFinishedEvent
: Receives a String
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 a FileInfo[]
object with the available files and shoots the RetrieveFileListEvent
event.
public SendFiles()
: Methods to send the files in the FileInfo[]
object.
private FtpClient_FtpCurrentProgressEvent(FtpProgress
ftpProgress)
. This method listens to the FtpCurrentProgressEvent
in FTPHelper
class; The event is set in the constructor of the FtpClient
class. This methods sets the FtpProgressEvent
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(String
Command, String
Verb, String
Verb2)
: writes the command with needed verb(s) to the StreamWriter
CreatePassiveFtpSocketInformation()
: when sending a file, the PASV command is used. The response gives a string
that must be converted to an IPEndPoint
with a port number.
ReadLineFromStream()
: After writing a command to the StreamWriter
, read the response stream. This response is send to the FtpCurrentProgressEvent
event.
ReadAllBytesFromTheFile(FileInfo
file)
: Read the bytes from the file that will be sent to the FTP server.
StartCurrentProgressEvent()
: Method to send the current FtpProgress
business object to the form via FtpClient
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 the ProgressBar
:public Int32 CurrentFileNr; public Int32 LastFileNr; public String FileName; public Int64 FileBytes; public Int64 SendFileBytes; public String FtpResponse;
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();
client.Connect(servername, port);
or:
TcpClient client = new TcpClient(servername, port);
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))
{
}
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
- 25th April, 2014
- Fixed
NULL
reference exception
- Reading all lines from the
stream
instead of one