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).
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.
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
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.
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
public SendFiles(): Methods to send the files in the
private FtpClient_FtpCurrentProgressEvent(<code>FtpProgress ftpProgress). This method listens to the
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, you will find 5 methods:
String Verb2): writes the command with needed verb(s) to the
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
ReadAllBytesFromTheFile(<code>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
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
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();
TcpClient client = new TcpClient(servername, port);
Note that you can also connect by using an
IPEndPoint. See here.
IDisposable so it is advised to use:
using (TcpClient client = new TcpClient(servername, port))
Basic FTP Knowledge
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;
string line = rdStrm.ReadLine();
MultipleLines = line.Substring(3, 1).Equals("-");
ftpProg.FtpResponse = line;
if (!MultipleLines) break;
Points of Interest
TcpClient is useful with older communication technologies that are still used today.
- 15th April, 2014
- 25th April, 2014
NULL reference exception
- Reading all lines from the
stream instead of one
- 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.
I started in the eightees with Basic and QuickBasic. When the ninetees started dBase was my thing. Close to the millenium years I swapped to C++ and since 2003 it is only programming in c#.
There is one thing about me.
Not that kind of OO guy and definately not an ORM-fan. I know a database to well to give the importance of data out in the hands of a tool.