I am unittesting a bit of code that can fetch files either from the local file system, or from http or ftp. To unittest it I created a simple method that uses the HTTPListener class from the BCL to run a one-off webserver on a different thread, it just serves a byte array that I send in and then shuts down. (See code for this below).
I was just wondering whether there is any simple way to do the same for ftp? There is no such thing as an FTPListener class in .NET (as far as I know). I don't know a lot about FTP but as far as I know there is a control channel and data channel, so I can imagine that it would be a bit more complicated than the http example below. So, any ideas, short of writing it from scratch using sockets? Any classes that I could use?
public static void Serve(int port, int statusCode, byte[] responseBody,
Dictionary<string,string> headers)
{
new Thread(delegate()
{
var listener = new HttpListener();
listener.Prefixes.Add(string.Format("http://localhost:{0}/", port));
listener.Start();
var context = listener.GetContext();
context.Response.StatusCode = statusCode;
context.Response.ContentLength64 = responseBody.Length;
if (headers != null)
{
foreach (string header in headers.Keys)
{
开发者_StackOverflow社区 context.Response.AddHeader(header, headers[header]);
}
}
context.Response.OutputStream.Write(responseBody, 0, responseBody.Length);
context.Response.OutputStream.Close();
listener.Stop();
}).Start();
}
FTP is a bit more complicated than HTTP, but not that much more. The control port is used for sending commands like authenticating, changing directory, requesting files, requesting to send files, etc. When a request that requires data is made, a second connection is used to send actual data. Depending on if you're using active or passive FTP, either the server will connect to the client or the client will connect again to the server.
We have a custom FTP client implementation we wrote in .NET that fully implements the client (from before when .NET had FTP support built in). It's only a few hundred lines of code.
If you can find an existing class that someone else has written and tested, then of course that's better. But if you need to do it yourself, it is doable. Just follow the spec and test it.
http://www.ietf.org/rfc/rfc959.txt
http://www.ietf.org/rfc/rfc1579.txt
A quick search turned up this: http://www.codeguru.com/csharp/csharp/cs_network/sockets/article.php/c7409/
If it isn't a "listener" it would provide a good start on one.
精彩评论