C# FTP上传代码

using System;
using System.IO;
using System.Net.Sockets;

namespace ftpClientUtil
{
    internal class FtpWebStream : Stream
    {
        private FtpWebResponse response;
        private NetworkStream dataStream;

        public FtpWebStream(NetworkStream dataStream, FtpWebResponse response)
        {
            this.dataStream = dataStream;
            this.response = response;
        }

        public override void Close()
        {
            response.Close();
            base.Close();
        }

        public override void Flush()
        {
            dataStream.Flush();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            return dataStream.Read(buffer, offset, count);
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotSupportedException("Seek not supported.");
        }

        public override void SetLength(long value)
        {
            throw new NotSupportedException("SetLength not supported.");
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            dataStream.Write(buffer, offset, count);
        }

        public override bool CanRead
        {
            get { return dataStream.CanRead; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }

        public override bool CanWrite
        {
            get { return dataStream.CanWrite; }
        }

        public override long Length
        {
            get { throw new NotSupportedException("Length not supported."); }
        }

        public override long Position
        {
            get
            {
                throw new NotSupportedException("Position not supported.");
            }
            set
            {
                throw new NotSupportedException("Position not supported.");
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace ftpClientUtil
{
    public class FtpWebRequest : WebRequest
    {
        private string username = "anonymous";
        internal string password = "someuser@someemail.com";

        private Uri uri;
        private bool binaryMode = true;
        private string method = "Get";

        internal FtpWebRequest(Uri uri)
        {
            this.uri = uri;
        }

        public string Username
        {
            get { return username; }
            set { username = value; }
        }

        public string Password
        {
            get { return password; }
            set { password = value; }
        }

        public bool BinaryMode
        {
            get { return binaryMode; }
            set { binaryMode = value; }
        }

        public override System.Uri RequestUri
        {
            get
            {
                return uri;
            }
        }

        public override string Method
        {
            get
            {
                return method;
            }
            set
            {
                method = value;
            }
        }

        public override WebResponse GetResponse()
        {
            FtpWebResponse response = new FtpWebResponse(this);
            return response;
        }
    }
}
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;

namespace ftpClientUtil
{
    public class FtpWebResponse : WebResponse
    {
        private FtpWebRequest request;
        private FtpClient client;

        internal FtpWebResponse(FtpWebRequest request)
        {
            this.request = request;
        }

        public override Stream GetResponseStream()
        {
            string hostname;
            string filename;
            GetUriComponents(request.RequestUri.ToString(), out hostname, out filename);

            //Connect to the Ftp server and get a stream
            client = new FtpClient(request.Username, request.password);
            client.Connect(hostname);

            NetworkStream dataStream = null;
            switch (request.Method)
            {
                case "Get":
                case "RETR":
                    dataStream = client.GetReadStram(filename, request.BinaryMode);
                    break;
                case "PUT":
                case "STOR":
                    dataStream = client.GetWriteStream(filename, request.BinaryMode);
                    break;
                default:
                    throw new WebException("Method " + request.Method + " not supported");
            }

            //create and return an FtpWebStream (to close the underlying objects)
            FtpWebStream ftpStream = new FtpWebStream(dataStream, this);
            return ftpStream;
        }

        private void GetUriComponents(string uri, out string hostname, out string fileName)
        {
            //Check that URI has at least 7 characters, or we'll get an error
            uri = uri.ToLower();
            if (uri.Length < 7)
                throw new UriFormatException("Invalid URI");

            //Check that URI starts "ftp://", and remove that from the start
            if (uri.Substring(0,6)!="ftp://")
                throw new NotSupportedException("Only FTP requests are supported");
            else
                uri=uri.Substring(6,uri.Length-6);

            //Divide the rest of the URI into the hostname and the filename
            string[] uriParts = uri.Split(new char[]{'/'},2);
            if (uriParts.Length != 2)
                throw new UriFormatException("Invalid URI");

            hostname = uriParts[0];
            fileName = uriParts[1];
        }

        public override void Close()
        {
            client.Close();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;

namespace ftpClientUtil
{
    public class FtpRequestCreator : IWebRequestCreate
    {
        public FtpRequestCreator()
        { }

        public System.Net.WebRequest Create(System.Uri uri)
        {
            return new FtpWebRequest(uri);
        }
    }
}
using System;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;

namespace ftpClientUtil
{
    internal sealed class FtpClient
    {
        private const int bufferSize = 65536;
        private NetworkStream controlStream;
        private NetworkStream dataStream;
        private TcpClient client;
        private string username;
        private string password;
        private TcpClient dataClient = null;

        public FtpClient(string username, string password)
        {
            this.username = username;
            this.password = password;
        }

        public void Connect(string hostname)
        {
            //Set the private fields representing the TCP control connection to
            //the server and the NetworkStream used to communicate with the server
            client = new TcpClient(hostname, 21);
            controlStream = client.GetStream();

            string responseMessage;
            if (GetResponse(out responseMessage) != 220)
            {
                throw new WebException(responseMessage);
            }
            Logon(username, password);
        }

        public int GetResponse(out string responseMessage)
        {
            //Read the response from the server, trim any nulls, and return it.
            byte[] response = new byte[client.ReceiveBufferSize];
            controlStream.Read(response, 0, response.Length);
            responseMessage = Encoding.ASCII.GetString(response).Replace("/0", "");
            return int.Parse(responseMessage.Substring(0, 3));
        }

        private void Logon(string username, string password)
        {
            //Send a USER FTP commnad. The server should repond with a 331 message to ask for the user's password
            string respMessage;
            int resp = SendCommand("USER " + username, out respMessage);

            if (resp != 331 && resp != 230)
                throw new UnauthorizedAccessException("Unable to login to the FTP server");

            if (resp != 230)
            {
                //Send a PASS FTP command. The server should respond with a 230 message to say that the user is now logged in.
                resp = SendCommand("PASS " + password, out respMessage);
                if (resp != 230)
                    throw new UnauthorizedAccessException("FTP server can't authenticate username");
            }
        }

        public NetworkStream GetReadStram(string filename, bool binaryMode)
        {
            return DownloadFile(filename, binaryMode);
        }

        public NetworkStream GetWriteStream(string filename, bool binaryMode)
        {
            return UploadFile(filename, binaryMode);
        }

        public NetworkStream DownloadFile(string filename, bool binaryMode)
        {
            if (dataClient == null)
                dataClient = CreateDataSocket();

            SetBinaryMode(binaryMode);
            string respMessage;
            int resp = SendCommand("RETR " + filename, out respMessage);

            if (resp != 150 && resp != 125)
                throw new WebException(respMessage);

            dataStream = dataClient.GetStream();
            return dataStream;
        }

        private NetworkStream UploadFile(string filename, bool binaryMode)
        {
            if (dataClient == null)
                dataClient = this.CreateDataSocket();

            //Set binary or ASCII mode
            SetBinaryMode(binaryMode);

            //Send a STOR command to say we want to upload a file
            string respMessage;
            int resp = SendCommand("STOR " + filename, out respMessage);

            //we should get a 150 resposne to say that the server is opening the data connection
            if (resp != 150 && resp != 125)
                throw new WebException("Can't upload file to the server");

            dataStream = dataClient.GetStream();
            return dataStream;
        }

        private void SetBinaryMode(bool binaryMode)
        {
            int resp;
            string respMessage;
            if (binaryMode)
                resp = SendCommand("TYPE I", out respMessage);
            else
                resp = SendCommand("TYPE A", out respMessage);

            if (resp != 200)
                throw new WebException(respMessage);
        }

        private TcpClient CreateDataSocket()
        {
            //request server to listen on a data port (not the default data port) and wait for a connection
            string respMessage;
            int resp = SendCommand("PASV", out respMessage);
            if (resp != 227)
                throw new WebException(respMessage);

            //The response includes the host address and port numner
            //IP address and port numner separated with ',' Create the IP address and port number
            int[] parts = new int[6];
            try
            {
                int index1 = respMessage.IndexOf('(');
                int index2 = respMessage.IndexOf(')');
                string endPointData = respMessage.Substring(index1+1,index2-index1-1);

                string [] endPointParts = endPointData.Split(',');

                for (int i=0;i<6;i++)
                    parts[i] = int.Parse(endPointParts[i]);
            }
            catch
            {
                throw new WebException("Malformed PASV reply: " + respMessage);
            }

            string ipAddress = parts[0] + "." + parts[1] + "." + parts[2] + "." + parts[3];
            int port = (parts[4] << 8) + parts[5];

            //Create a client socket
            TcpClient dataClient = new TcpClient();

            //Connect to the data poer of the server
            try {
                IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse(ipAddress),port);
                dataClient.Connect(remoteEP);
            }
            catch (Exception)
            {
                throw new WebException("Can't connected to remote server");
            }
            return dataClient;
        }

        public void Close()
        {
            if (dataStream != null)
            {
                dataStream.Close();
                dataStream = null;
            }
           
            string respMessage;
            GetResponse(out respMessage);

            Logoff();

            //Close the control TcpClient and NetworkStream
            controlStream.Close();
            client.Close();
        }

        public void Logoff()
        {
            //Send the QUIT command to log off from the server
            string respMessage;
            SendCommand("STAT", out respMessage);   //Test only
            GetResponse(out respMessage);           //STAT has 2 response lines!

            SendCommand("QUIT", out respMessage);
        }

        internal int SendCommand(string command, out string respMessage)
        {
            //Convert the command string (terminated with a CRLF) into a byte array, and write it to control stream.
            byte[] request = Encoding.ASCII.GetBytes(command + "/r/n");
            controlStream.Write(request, 0, request.Length);
            return GetResponse(out respMessage);
        }
    }
}
以下是客户端的调用:
using System;
using System.IO;
using System.Net;
using ftpClientUtil;

namespace ConsoleApplication1
{
    class Program
    {
        const int bufferSize = 65536;
        static void Main(string[] args)
        {
            //Register the ftp schema.
            //Alternatively, a config file could be used
            WebRequest.RegisterPrefix("ftp", new FtpRequestCreator());

            //UploadDemo();
        }

        //Upload a file using FtpWebRequest
        public static void UploadDemo()
        {
            ftpClientUtil.FtpWebRequest req = (ftpClientUtil.FtpWebRequest)WebRequest.Create("ftp://192.168.0.1/demofile.bmp");
            req.Username = "Administrator";
            req.Password = "secret";
            req.Method = "PUT"; //STOR or PUT
            req.BinaryMode = true;
            Stream writeStream = req.GetResponse().GetResponseStream();

            FileStream fs = new FileStream(@"c:/temp/cool.bmp", FileMode.Open);

            byte[] buffer = new byte[bufferSize];
            int read;
            while ((read = fs.Read(buffer, 0, bufferSize)) > 0)
                writeStream.Write(buffer, 0, bufferSize);

            writeStream.Close();
            fs.Close();
        }

        //Downlaod a file using FtpWebRequest
        public static void DownloadDemo()
        {
            ftpClientUtil.FtpWebRequest req = (ftpClientUtil.FtpWebRequest)WebRequest.Create("ftp://192.168.0.1/sample.bmp");

            //defualts:
            req.Username = "anonymous";
            req.Password = "someuser@somemail.com";
            req.BinaryMode = true;
            req.Method = "GET";

            ftpClientUtil.FtpWebResponse resp = (ftpClientUtil.FtpWebResponse)req.GetResponse();
            Stream stream = resp.GetResponseStream();

            //Read a binary file
            FileStream fs = new FileStream(@"c:/temp/sample.bmp", FileMode.Create);
            byte[] buffer = new byte[bufferSize];
            int count;
            do
            {
                Array.Clear(buffer, 0, bufferSize);
                count = stream.Read(buffer, 0, bufferSize);
                fs.Write(buffer, 0, count);
            } while (count > 0);

            stream.Close();
            fs.Close();

            //read a text file
            StreamReader reader = new StreamReader(stream);
            string line;
            while ((line = reader.ReadLine()) != null)
                Console.WriteLine(line);

            reader.Close();
        }
    }
}
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace TCPServerDemo
{
    class ClientHandler
    {
        public TcpClient clientSocket;

        public void RunClient()
        {
            //Create the stream classes
            Console.WriteLine(clientSocket.Client.AddressFamily.ToString());
            StreamReader readerStream = new StreamReader(clientSocket.GetStream());
            NetworkStream writestream = clientSocket.GetStream();

            string returnData = readerStream.ReadLine();
            string userName = returnData;

            Console.WriteLine("Welcome " + userName + " to the Server");
            while (true)
            {
                returnData = readerStream.ReadLine();
                if (returnData.IndexOf("QUIT") > -1)
                {
                    Console.WriteLine("Bye Bye " + userName);
                    break;
                }

                Console.WriteLine(userName + ": " + returnData);
                returnData += "/r/n";

                byte[] dataWrite = Encoding.ASCII.GetBytes(returnData);
                writestream.Write(dataWrite, 0, dataWrite.Length);
            }
            clientSocket.Close();
        }
    }
    public class EchoServer
    {
        const int ECHO_PORT = 8080;
        public static int nClient = 0;

        static void Main(string[] args)
        {
            try
            {
                //Bind the Server to local port
                TcpListener clientListener = new TcpListener(IPAddress.Parse("127.0.0.1"),ECHO_PORT);

                //start to listen
                clientListener.Start();

                Console.WriteLine("Waiting for connection...");

                while (true)
                {
                    //Accept the connection
                    TcpClient client = clientListener.AcceptTcpClient();
                    ClientHandler cHandler = new ClientHandler();

                    //pass value to the ClientHandler object
                    cHandler.clientSocket = client;
                    string ipaddressport = client.Client.RemoteEndPoint.ToString();
                    Console.WriteLine(ipaddressport.Substring(0, ipaddressport.IndexOf(":")) + "--------------"+ipaddressport.Substring(ipaddressport.IndexOf(":")+1), ipaddressport.Length - ipaddressport.IndexOf(":")-1);
                    //Create a new thread for the client
                    Thread clientThread = new Thread(new ThreadStart(cHandler.RunClient));
                    clientThread.Start();
                }
                clientListener.Stop();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
using System;
using System.Net;
using System.IO;
using System.Net.Sockets;
using System.Text;

namespace TCPClientDemo
{
    class Program
    {
        const int ECHO_PORT = 8080;
        static void Main(string[] args)
        {
            Console.Write("Your UserName:");
            string userName = Console.ReadLine();
            Console.WriteLine("-----Logged in-----");

            try
            {
                //Create a connection with the Chatserver
                TcpClient eClient = new TcpClient("127.0.0.1", ECHO_PORT);

                //Create the stream classes
                StreamReader readerStream = new StreamReader(eClient.GetStream());
                NetworkStream writeStream = eClient.GetStream();

                string dataToSend;

                dataToSend = userName;
                dataToSend += "/r/n";

                //Send username to the server
                byte[] data = Encoding.ASCII.GetBytes(dataToSend);
                writeStream.Write(data, 0, data.Length);

                while (true)
                {
                    Console.WriteLine(userName + ":");
                    //Read line from server
                    dataToSend = Console.ReadLine();
                    dataToSend += "/r/n";
                    data = Encoding.ASCII.GetBytes(dataToSend);
                    writeStream.Write(data, 0, data.Length);
                    //If QUIT is sent, then quit application
                    if (dataToSend.IndexOf("QUIT") > -1)
                        break;

                    string returnData;

                    //Receive response from server
                    returnData = readerStream.ReadLine();
                    Console.WriteLine("Server: " + returnData);
                }

                //Close TcpClient
                eClient.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}

TCP也就是基于SOCKET传输,上面是简单的例子,难一些的是把文件拆分,下面是一个UDP的文件传输,改改可以用在上面的TCP上
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Xml.Serialization;
using System.Diagnostics;
using System.Threading;

namespace FileSender
{
public class FileSender
{
//File details (Req. for receiver)
[Serializable]
public class FileDetails
{
public string FILETYPE="";
public long FILESIZE=0;
}
private static FileDetails fileDet = new FileDetails();

//UdpClient - related fields
private static IPAddress remoteIPAddress;
private const int remotePort=5002;
private static UdpClient sender = new UdpClient();
private static IPEndPoint endPoint;
//Filestream object
private static FileStream fs;

[STAThread]
static void Main(string[] args)
{
try
{
//Get remote IP address and create IPEndPoint
                //Console.WriteLine("Enter Remote IP address");
                remoteIPAddress = IPAddress.Parse("127.255.255.255");// IPAddress.Parse(Console.ReadLine().ToString());
endPoint = new IPEndPoint(remoteIPAddress,remotePort);

//Get file path. (IMP:file size should be less than 8K)
                Console.WriteLine("Enter file path and name to send.");
                fs = new FileStream(@Console.ReadLine().ToString(), FileMode.Open, FileAccess.Read);

                //if (fs.Length > 8192)
                //{
                //    Console.WriteLine("This version transfers files with size <8192 bytes");
                //    sender.Close();
                //    fs.Close();
                //    return;
                //}

SendFileInfo();
Thread.Sleep(2000);

                //SendFile();
                #region big
                byte[] a = Encoding.ASCII.GetBytes(((char)3).ToString());

                long remainlength = fs.Length - (long)(fs.Length / 8192) * 8192 + 1;
                if (fs.Length > 8192)
                {
                    for (int i = 0; i < fs.Length / 8192; i++)
                    {
                        byte[] fixbyte = new byte[8192];
                        fs.Read(fixbyte, 0, 8192);
                        SendFile(fixbyte);
                        Console.WriteLine("send " + (i + 1).ToString() + " times");
                    }
                    byte[] remainbyte = new byte[remainlength];
                    fs.Read(remainbyte, 0, (int)remainlength - 1);
                    Array.Copy(Encoding.ASCII.GetBytes(((char)3).ToString()), 0, remainbyte, remainbyte.Length - 1, 1);
                    SendFile(remainbyte);
                }
                #endregion

                Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

public static void SendFileInfo()
{
//Get file type or extension
fileDet.FILETYPE = fs.Name.Substring((int)fs.Name.Length -3,3);
//Get file length(futrue purpose)
fileDet.FILESIZE = fs.Length;

XmlSerializer fileSerializer = new XmlSerializer(typeof(FileDetails));
MemoryStream stream = new MemoryStream();
//Serialize object
fileSerializer.Serialize(stream,fileDet);
//Stream to byte
stream.Position = 0;
byte[] bytes = new byte[stream.Length];
stream.Read(bytes,0,Convert.ToInt32(stream.Length));

Console.WriteLine("Sending file details...");
//Send file details
            sender.Send(bytes, bytes.Length, endPoint);
stream.Close();
}

public static void SendFile()
{
//Creating a file stream
byte[] bytes = new byte[fs.Length];
//stream to bytes
fs.Read(bytes,0,bytes.Length);
Console.WriteLine("Sending file...size=" + fs.Length + " bytes");
try
{
sender.Send(bytes,bytes.Length, endPoint);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
finally
{
//Clean up
fs.Close();
sender.Close();
}
Console.Read();
Console.WriteLine("File sent sucessfully.");
}

        public static void SendFile(byte[] subfilebytes)
        {
            try
            {
                sender.Send(subfilebytes, subfilebytes.Length, endPoint);
                //Console.WriteLine(Encoding.ASCII.GetString(subfilebytes));
            }
            catch (Exception e)
            {
                Console.WriteLine(e.ToString());
            }
            finally
            {
                //sender.Close();
            }
            Console.WriteLine("Sub File Part sent sucessfully.");
        }
}
}
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Diagnostics;
using System.Text;
using System.Xml.Serialization;

namespace FileReceive
{
public class FileRecv
{
[Serializable]
public class FileDetails
{
public string FILETYPE = "";
public long FILESIZE = 0;
}

private static FileDetails fileDet;
//UdpClient vars
private static int localPort = 5002;
private static UdpClient receivingUdpClient = new UdpClient(localPort);
private static IPEndPoint RemoteIpEndPoint = null;
        private static FileStream fs;
        private static byte[] receiveBytes = new byte[0];
        private static byte[] subreceiveBytes = new byte[0];


[STAThread]
static void Main(string[] args)
{
//Get the file details
GetFileDetails();
//Receive file;
ReceiveFile();
}

private static void GetFileDetails()
{
try
{
Console.WriteLine("-----------------Waiting to get File Details!!----------------");
//Receive File info
                byte[] receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
                Console.WriteLine("receive file details!!");

                XmlSerializer fileSerializer = new XmlSerializer(typeof(FileDetails));
                MemoryStream stream1 = new MemoryStream();

                //Received byte to stream
                stream1.Write(receiveBytes, 0, receiveBytes.Length);
                stream1.Position = 0; //IMP

                //call the Deserialize method and cast to the object type
                fileDet = (FileDetails)fileSerializer.Deserialize(stream1);
                Console.WriteLine("Receive file of type." + fileDet.FILETYPE + " whose size is " + fileDet.FILESIZE.ToString() + " bytes");
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}

        public static void ReceiveFile()
        {
            int insertpoint=0,i=0;
            byte[] a = new byte[1];
            try
            {
                receiveBytes = new byte[fileDet.FILESIZE];
                Console.WriteLine("--------------Waiting to get File-------------------");

                //Receive file
                //receiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
                //Console.WriteLine("------File received...Saving....");

                Create temp file from received file extension
                //fs = new FileStream("temp." + fileDet.FILETYPE, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                //fs.Write(receiveBytes, 0, receiveBytes.Length);

                //Console.WriteLine("---File Saved----" + receiveBytes.Length.ToString());
                //Console.WriteLine("---Opening file with associated program----");

                //Process.Start(fs.Name); //Opens file with associated program

                #region big
                while (true)
                {
                    subreceiveBytes = receivingUdpClient.Receive(ref RemoteIpEndPoint);
                    Array.Copy(subreceiveBytes, subreceiveBytes.Length - 1, a, 0, 1);
                    string returnData = Encoding.ASCII.GetString(a);
                    if (returnData.IndexOf((char)3) > -1)
                    {
                        Array.Copy(subreceiveBytes, 0, receiveBytes, insertpoint, subreceiveBytes.Length - 1);

                        //Convert and display data
                        Console.WriteLine("------File received...Saving....");

                        //Create temp file from received file extension
                        fs = new FileStream("temp." + fileDet.FILETYPE, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                        fs.Write(receiveBytes, 0, receiveBytes.Length);

                        Console.WriteLine("---File Saved----" + receiveBytes.Length.ToString());
                        Console.WriteLine("---Opening file with associated program----");

                        Process.Start(fs.Name); //Opens file with associated program
                    }
                    else
                    {
                        i++;
                        Console.WriteLine(i.ToString());
                        Array.Copy(subreceiveBytes, 0, receiveBytes, insertpoint, subreceiveBytes.Length);
                        insertpoint += subreceiveBytes.Length;
                    }
                }
                #endregion
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            finally
            {
                fs.Close();
                receivingUdpClient.Close();
            }
        }
}
}
 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
用VS编写的FTP服务器软件,C#网络程序编程学习用。 代码: using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; using System.Windows.Forms; namespace FtpServer { public partial class FtpServerForm : Form { TcpListener myTcpListener = null; private Thread listenThread; // 保存用户名和密码 Dictionary users; public FtpServerForm() { InitializeComponent(); // 初始化用户名和密码 users = new Dictionary(); users.Add("admin", "admin"); // 设置默认的主目录 tbxFtpRoot.Text = "F:/MyFtpServerRoot/"; IPAddress[] ips = Dns.GetHostAddresses(""); tbxFtpServerIp.Text = ips[5].ToString(); tbxFtpServerPort.Text = "21"; lstboxStatus.Enabled = false; } // 启动服务器 private void btnFtpServerStartStop_Click(object sender, EventArgs e) { if (myTcpListener == null) { listenThread = new Thread(ListenClientConnect); listenThread.IsBackground = true; listenThread.Start(); lstboxStatus.Enabled = true; lstboxStatus.Items.Clear(); lstboxStatus.Items.Add("已经启动Ftp服务..."); btnFtpServerStartStop.Text = "停止"; } else { myTcpListener.Stop(); myTcpListener = null; listenThread.Abort(); lstboxStatus.Items.Add("Ftp服务已停止!"); lstboxStatus.TopIndex = lstboxStatus.Items.Count - 1; btnFtpServerStartStop.Text = "启动"; } } // 监听端口,处理客户端连接 private void ListenClientConnect() { myTcpListener = new TcpListener(IPAddress.Parse(tbxFtpServerIp.Text), int.Parse(tbxFtpServerPort.Text)); // 开始监听传入的请求 myTcpListener.Start(); AddInfo("启动FTP服务成功!"); AddInfo("Ftp服务器运行中...[点击”停止“按钮停止FTP服务]"); while (true) { try { // 接收连接请求 TcpClient tcpClient = myTcpListener.AcceptTcpClient(); AddInfo(string.Format("客户端({0})与本机({1})建立Ftp连接", tcpClient.Client.RemoteEndPoint, myTcpListener.LocalEndpoint)); User user = new User(); user.commandSession = new UserSeesion(tcpClient); user.workDir = tbxFtpRoot.Text; Thread t = new Thread(UserProcessing); t.IsBackground = true; t.Start(user); } catch { break; } } } // 处理客户端用户请求 private void UserProcessing(object obj) { User user = (User)obj; string sendString = "220 FTP Server v1.0"; RepleyCommandToUser(user, sendString); while (true) { string receiveString = null; try { // 读取客户端发来的请求信息 receiveString = user.commandSession.streamReader.ReadLine(); } catch(Exception ex) { if (user.commandSession.tcpClient.Connected == false) { AddInfo(string.Format("客户端({0}断开连接!)", user.commandSession.tcpClient.Client.RemoteEndPoint)); } else { AddInfo("接收命令失败!" + ex.Message); } break; } if (receiveString == null) { AddInfo("接收字符串为null,结束线程!"); break; } AddInfo(string.Format("来自{0}:[{1}]", user.commandSession.tcpClient.Client.RemoteEndPoint, receiveString)); // 分解客户端发来的控制信息中的命令和参数 string command = receiveString; string param = string.Empty; int index = receiveString.IndexOf(' '); if (index != -1) { command = receiveString.Substring(0, index).ToUpper(); param = receiveString.Substring(command.Length).Trim(); } // 处理不需登录即可响应的命令(这里只处理QUIT) if (command == "QUIT") { // 关闭TCP连接并释放与其关联的所有资源 user.commandSession.Close(); return; } else { switch (user.loginOK) { // 等待用户输入用户名: case 0: CommandUser(user, command, param); break; // 等待用户输入密码 case 1: CommandPassword(user, command, param); break; // 用户名和密码验证正确后登陆 case 2: switch (command) { case "CWD": CommandCWD(user, param); break; case "PWD": CommandPWD(user); break; case "PASV": CommandPASV(user); break; case "PORT": CommandPORT(user, param); break; case "LIST": CommandLIST(user, param); break; case "NLIST": CommandLIST(user, param); break; // 处理下载文件命令 case "RETR": CommandRETR(user, param); break; // 处理上传文件命令 case "STOR": CommandSTOR(user, param); break; // 处理删除命令 case "DELE": CommandDELE(user, param); break; // 使用Type命令在ASCII和二进制模式进行变换 case "TYPE": CommandTYPE(user, param); break; default: sendString = "502 command is not implemented."; RepleyCommandToUser(user, sendString); break; } break; } } } } // 想客户端返回响应码 private void RepleyCommandToUser(User user, string str) { try { user.commandSession.streamWriter.WriteLine(str); AddInfo(string.Format("向客户端({0})发送[{1}]", user.commandSession.tcpClient.Client.RemoteEndPoint, str)); } catch { AddInfo(string.Format("向客户端({0})发送信息失败", user.commandSession.tcpClient.Client.RemoteEndPoint)); } } // 向屏幕输出显示状态信息(这里使用了委托机制) private delegate void AddInfoDelegate(string str); private void AddInfo(string str) { // 如果调用AddInfo()方法的线程与创建ListView控件的线程不在一个线程时 // 此时利用委托在创建ListView的线程上调用 if (lstboxStatus.InvokeRequired == true) { AddInfoDelegate d = new AddInfoDelegate(AddInfo); this.Invoke(d, str); } else { lstboxStatus.Items.Add(str); lstboxStatus.TopIndex = lstboxStatus.Items.Count - 1; lstboxStatus.ClearSelected(); } } #region 处理各个命令 #region 登录过程,即用户身份验证过程 // 处理USER命令,接收用户名但不进行验证 private void CommandUser(User user, string command, string param) { string sendString = string.Empty; if (command == "USER") { sendString = "331 USER command OK, password required."; user.userName = param; // 设置loginOk=1为了确保后面紧接的要求输入密码 // 1表示已接收到用户名,等到接收密码 user.loginOK = 1; } else { sendString = "501 USER command syntax error."; } RepleyCommandToUser(user, sendString); } // 处理PASS命令,验证用户名和密码 private void CommandPassword(User user, string command, string param) { string sendString = string.Empty; if (command == "PASS") { string password = null; if (users.TryGetValue(user.userName, out password)) { if (password == param) { sendString = "230 User logged in success"; // 2表示登录成功 user.loginOK = 2; } else { sendString = "530 Password incorrect."; } } else { sendString = "530 User name or password incorrect."; } } else { sendString = "501 PASS command Syntax error."; } RepleyCommandToUser(user, sendString); // 用户当前工作目录 user.currentDir = user.workDir; } #endregion #region 文件管理命令 // 处理CWD命令,改变工作目录 private void CommandCWD(User user, string temp) { string sendString = string.Empty; try { string dir = user.workDir.TrimEnd('/') + temp; // 是否为当前目录的子目录,且不包含父目录名称 if (Directory.Exists(dir)) { user.currentDir = dir; sendString = "250 Directory changed to '" + dir + "' successfully"; } else { sendString = "550 Directory '" + dir + "' does not exist"; } } catch { sendString = "502 Directory changed unsuccessfully"; } RepleyCommandToUser(user,sendString); } // 处理PWD命令,显示工作目录 private void CommandPWD(User user) { string sendString = string.Empty; sendString = "257 '" + user.currentDir + "' is the current directory"; RepleyCommandToUser(user, sendString); } // 处理LIST/NLIST命令,想客户端发送当前或指定目录下的所有文件名和子目录名 private void CommandLIST(User user, string parameter) { string sendString = string.Empty; DateTimeFormatInfo dateTimeFormat = new CultureInfo("en-US", true).DateTimeFormat; // 得到目录列表 string[] dir = Directory.GetDirectories(user.currentDir); if (string.IsNullOrEmpty(parameter) == false) { if (Directory.Exists(user.currentDir + parameter)) { dir = Directory.GetDirectories(user.currentDir + parameter); } else { string s = user.currentDir.TrimEnd('/'); user.currentDir = s.Substring(0, s.LastIndexOf("/") + 1); } } for (int i = 0; i < dir.Length; i++) { string folderName = Path.GetFileName(dir[i]); DirectoryInfo d = new DirectoryInfo(dir[i]); // 按下面的格式输出目录列表 sendString += @"dwr-\t" + Dns.GetHostName() + "\t" + dateTimeFormat.GetAbbreviatedMonthName(d.CreationTime.Month) + d.CreationTime.ToString(" dd yyyy") + "\t" + folderName + Environment.NewLine; } // 得到文件列表 string[] files = Directory.GetFiles(user.currentDir); if (string.IsNullOrEmpty(parameter) == false) { if (Directory.Exists(user.currentDir + parameter + "/")) { files = Directory.GetFiles(user.currentDir + parameter + "/"); } } for (int i = 0; i 1024的随机端口 // 下面这个运算算法只是为了得到一个大于1024的端口值 port = random1 << 8 | random2; try { user.dataListener = new TcpListener(localip, port); AddInfo("TCP 数据连接已打开(被动模式)--" + localip.ToString() + ":" + port); } catch { continue; } user.isPassive = true; string temp = localip.ToString().Replace('.', ','); // 必须把端口号IP地址告诉客户端,客户端接收到响应命令后, // 再通过新的端口连接服务器的端口P,然后进行文件数据传输 sendString = "227 Entering Passive Mode(" + temp + "," + random1 + "," + random2 + ")"; RepleyCommandToUser(user, sendString); user.dataListener.Start(); break; } } // 处理PORT命令,使用主动模式进行传输 private void CommandPORT(User user, string portstring) { // 主动模式时,客户端必须告知服务器接收数据的端口号,PORT 命令格式为:PORT address // address参数的格式为i1、i2、i3、i4、p1、p2,其中i1、i2、i3、i4表示IP地址 // 下面通过.字符串来组合这四个参数得到IP地址 // p1、p2表示端口号,下面通过int.Parse(temp[4]) << 8) | int.Parse(temp[5] // 这个算法来获得一个大于1024的端口来发送给服务器 string sendString = string.Empty; string[] temp = portstring.Split(','); string ipString = "" + temp[0] + "." + temp[1] + "." + temp[2] + "." + temp[3]; // 客户端发出PORT命令把客户端的IP地址和随机的端口告诉服务器 int portNum = (int.Parse(temp[4]) < 0) { user.dataSession.binaryWriter.Write(bytes, 0, count); user.dataSession.binaryWriter.Flush(); count = binaryReader.Read(bytes, 0, bytes.Length); } } else { StreamReader streamReader = new StreamReader(fs); while (streamReader.Peek() > -1) { user.dataSession.streamWriter.WriteLine(streamReader.ReadLine()); } } AddInfo("...]发送完毕!"); } finally { user.dataSession.Close(); fs.Close(); } } // 使用数据连接接收文件流(客户端发送上传文件功能) private void ReadFileByUserSession(User user, FileStream fs) { AddInfo("接收用户上传数据(文件流):[..."); try { if (user.isBinary) { byte[] bytes = new byte[1024]; BinaryWriter binaryWriter = new BinaryWriter(fs); int count = user.dataSession.binaryReader.Read(bytes, 0, bytes.Length); while (count > 0) { binaryWriter.Write(bytes, 0, count); binaryWriter.Flush(); count = user.dataSession.binaryReader.Read(bytes, 0, bytes.Length); } } else { StreamWriter streamWriter = new StreamWriter(fs); while (user.dataSession.streamReader.Peek() > -1) { streamWriter.Write(user.dataSession.streamReader.ReadLine()); streamWriter.Flush(); } } AddInfo("...]接收完毕"); } finally { user.dataSession.Close(); fs.Close(); } } private void label3_Click(object sender, EventArgs e) { } } }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值