A C# FTP Server
Introduction
This is a fully functional FTP server that works with Internet Explorer and Netscape. I think the code itself is self explanatory. Eveything starts with a main form (MainForm.cs). Each user's starting directories are set up in UserForm.cs. There are some points of note:
Point 1: Adding Users
You must add users first, before using the FTP server.
The buttons in the user's dialog operate only if a user is selected.
Point 2: Functionality
This server will work with most clients, including Internet Explorer and Netscape Navigator. Each use a different method of transferring data (see below for a link to the FTP specification that gives more information).
Point 3: The FTP Server Is in an Assembly
Now, why do this? Surely you won't ever want to use an FTP server elsewhere? Nope! In actual fact, I've come across several usages of the FTP protocol other than just file transfer. Which brings me to Point 4...
Point 4: The Interface to the File System Is Replaceable
All file system accesses (for example, file open/write, list directory files, and so forth) go through a set of interfaces (see Assembly.Ftp.FileSystem.IFile, and so on).
The class factory for the file system object—the object that creates the file system object (Assembly.Ftp.FileSystem.IFileSystemClassFactory)—is passed in to the FTP server on creation. You can replace this with whatever you want (derived from IFileSystemClassFactory) and create classes that derive from IFileSystem, IFile, and IFileInfo to get the FTP server to do what you want.
Now, why do this? Well, this gives a huge amount of flexibility of use for this server. You could, for instance, change the FTP server so that it addresses the Registry and not the file system. You could even get it to address a database, or could use it as an external interface to access data in a large application.
Limitations
There is one limitation of the system:
- "ABOR" doesn't work (abortion from downloading/uploading files). Basically, the send and receive are done on the same thread as the commands instead of a seperate one. There's no reason why this can't be changed.
References
The vast majority of the information for building this site came from http://cr.yp.to/ftp.html, which is a really excellent source.
Conclusion
The FTP server is pretty much self explanatory, really. I don't think I need to add anything else here. And, how did I find C#? Well, considering I had an operational FTP server inside of two days, without knowing what the protocol was when I started, I'm really impressed. It's taken me a while to realise how good C# is (especially when taken with C++ .NET assemblies), but I'm a big fan now.
I hope you find this code useful.

Comments
Unable to upload files
Posted by Cristian H. on 03/21/2013 01:53pmHi, I am trying to upload a file to the FTP server, from another C# application: System.IO.Stream _Stream = _FtpWebRequest.GetRequestStream(); but I always get this error: "The remote server returned an error: (220) 220 Password ok, FTP server ready" This is not an error, but only a message. Could you please help me? Thank you!
ReplyLicense?
Posted by William Rawls on 09/18/2012 03:03pmIs this code licensed for use under any particular license? (GNU, Berkley, PHP, etc)
ReplyCross threaded error... m_listBoxMessages
Posted by Fonz on 04/04/2012 03:55amMainform.cs method MessageHandler_Message line 198 I get a cross threaded exception. I fixed it this way... Can also use the check m_listBoxMessages.InvokeRequired .... private void MessageHandler_Message(int nId, string sMessage) { try { m_listBoxMessages.BeginUpdate(); int nItem = m_listBoxMessages.Items.Add(string.Format("({0}) {2}", nId, System.DateTime.Now, sMessage)); if (m_listBoxMessages.Items.Count 5000) { m_listBoxMessages.Items.RemoveAt(0); } if (m_listBoxMessages.SelectedIndex
Replyappend file corrupts files - here is the fix
Posted by giopin on 04/28/2011 09:55amAppendCommandHandler.cs - line 39 original: while (nReceived > 0) { nReceived = socketReply.Receive(abData); file.Write(abData, nReceived); } fixed: while (nReceived > 0) { file.Write(abData, nReceived); nReceived = socketReply.Receive(abData); }ReplyAnother bug: CFtpServer.cs
Posted by broj137 on 04/28/2011 03:11amThe problem is m_apConnections.Count, because it is in the for weather, and it's not fixed. for each handler.Stop() it is decrased for one, so we have situation to remove only half of opened connections. public void Stop() { for (int nConnection = 0 ; nConnection < m_apConnections.Count; nConnection++) { FtpSocketHandler handler = m_apConnections[nConnection] as FtpSocketHandler; handler.Stop(); } m_socketListen.Stop(); m_theThread.Join(); } one possible solution: public void Stop() { for (int connCnt = m_apConnections.Count - 1; connCnt >= 0; connCnt--) { FtpSocketHandler handler = m_apConnections[connCnt] as FtpSocketHandler; handler.Stop(); } m_socketListen.Stop(); m_theThread.Join(); }ReplyHow do you?
Posted by ThePlague122 on 08/07/2010 08:23pmHow do you compile these dlls... plz help.
-
ReplyRe : How do you compile these dlls
Posted by darwen on 08/08/2010 08:36amOpen the solution file in the app folder (csftp.sln), let visual studio convert it and then just build.
ReplyGreat Article
Posted by krishm on 10/31/2008 06:18amHi Darwen I just read ur article n downloaded ur code n I really wanted to tell u that its a great article and helped me a lot. I was wondering if u cud also come uo with something about changing the permission of the files on the server. Thanks and Regards Krishnendu Mukherjee
ReplyGood job
Posted by zombi82 on 02/15/2007 05:55amJasny i przejrzysty kod serwera FTP, najlepszy jaki znalazEem w necie. Thanks darwen.
ReplyI find a little error in this program
Posted by dragon829 on 08/22/2006 03:38amIn this program,whether choose an item to remove a user,it will show messagebox ,is it a little error?I correct it as follow: private void m_buttonRemoveUser_Click(object sender, System.EventArgs e) { if (m_listViewUsers.SelectedItems.Count == 0) { MessageBox.Show("Please select a user in the list", "CSFtp"); } else { for (int nIndex = 0 ; nIndex < m_listViewUsers.SelectedItems.Count ; nIndex++) { ListViewItem item = m_listViewUsers.SelectedItems[nIndex]; string sUser = item.SubItems[0].Text; Assemblies.Ftp.UserData.Get().RemoveUser(sUser); m_listViewUsers.Items.Remove(item); } } }ReplyUpdates
Posted by darwen on 08/22/2005 04:37pmThe Assemblies.General C++.NET dll has now been removed and replaced with a C# assembly with full source. Also the problem with localhost connection has been addressed (thanks jgorlick).
ReplyLoading, Please Wait ...