C# 的FTP源代码
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Resources;
using System.Text.RegularExpressions;
using System.Collections;
namespace crFTP
{
/// <summary>
/// FTP类
/// </summary>
public class FTP
{
#region 变量声明
/// <summary>
/// 服务器连接地址
/// </summary>
public string server;
/// <summary>
/// 登陆帐号
/// </summary>
public string user;
/// <summary>
/// 登陆口令
/// </summary>
public string pass;
/// <summary>
/// 端口号
/// </summary>
public int port;
/// <summary>
/// 无响应时间(FTP在指定时间内无响应)
/// </summary>
public int timeout;
/// <summary>
/// 服务器错误状态信息
/// </summary>
public string errormessage;
/// <summary>
/// 服务器状态返回信息
/// </summary>
private string messages;
/// <summary>
/// 服务器的响应信息
/// </summary>
private string responseStr;
/// <summary>
/// 链接模式(主动或被动,默认为被动)
/// </summary>
private bool passive_mode;
/// <summary>
/// 上传或下载信息字节数
/// </summary>
private long bytes_total;
/// <summary>
/// 上传或下载的文件大小
/// </summary>
private long file_size;
/// <summary>
/// 主套接字
/// </summary>
private Socket main_sock;
/// <summary>
/// 要链接的网络地址终结点
/// </summary>
private IPEndPoint main_ipEndPoint;
/// <summary>
/// 侦听套接字
/// </summary>
private Socket listening_sock;
/// <summary>
/// 数据套接字
/// </summary>
private Socket data_sock;
/// <summary>
/// 要链接的网络数据地址终结点
/// </summary>
private IPEndPoint data_ipEndPoint;
/// <summary>
/// 用于上传或下载的文件流对象
/// </summary>
private FileStream file;
/// <summary>
/// 与FTP服务器交互的状态值
/// </summary>
private int response;
/// <summary>
/// 读取并保存当前命令执行后从FTP服务器端返回的数据信息
/// </summary>
private string bucket;
#endregion
#region 构造函数
/// <summary>
/// 构造函数
/// </summary>
public FTP()
{
server = null;
user = null;
pass = null;
port = 21;
passive_mode = true;
main_sock = null;
main_ipEndPoint = null;
listening_sock = null;
data_sock = null;
data_ipEndPoint = null;
file = null;
bucket = "";
bytes_total = 0;
timeout = 10000; //无响应时间为10秒
messages = "";
errormessage = "";
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="server">服务器IP或名称</param>
/// <param name="user">登陆帐号</param>
/// <param name="pass">登陆口令</param>
public FTP(string server, string user, string pass)
{
this.server = server;
this.user = user;
this.pass = pass;
port = 21;
passive_mode = true;
main_sock = null;
main_ipEndPoint = null;
listening_sock = null;
data_sock = null;
data_ipEndPoint = null;
file = null;
bucket = "";
bytes_total = 0;
timeout = 10000; //无响应时间为10秒
messages = "";
errormessage = "";
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="server">服务器IP或名称</param>
/// <param name="port">端口号</param>
/// <param name="user">登陆帐号</param>
/// <param name="pass">登陆口令</param>
public FTP(string server, int port, string user, string pass)
{
this.server = server;
this.user = user;
this.pass = pass;
this.port = port;
passive_mode = true;
main_sock = null;
main_ipEndPoint = null;
listening_sock = null;
data_sock = null;
data_ipEndPoint = null;
file = null;
bucket = "";
bytes_total = 0;
timeout = 10000; //无响应时间为10秒
messages = "";
errormessage = "";
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="server">服务器IP或名称</param>
/// <param name="port">端口号</param>
/// <param name="user">登陆帐号</param>
/// <param name="pass">登陆口令</param>
/// <param name="mode">链接方式</param>
public FTP(string server, int port, string user, string pass, int mode)
{
this.server = server;
this.user = user;
this.pass = pass;
this.port = port;
passive_mode = mode <= 1 ? true : false;
main_sock = null;
main_ipEndPoint = null;
listening_sock = null;
data_sock = null;
data_ipEndPoint = null;
file = null;
bucket = "";
bytes_total = 0;
this.timeout = 10000; //无响应时间为10秒
messages = "";
errormessage = "";
}
/// <summary>
/// 构造函数
/// </summary>
/// <param name="server">服务器IP或名称</param>
/// <param name="port">端口号</param>
/// <param name="user">登陆帐号</param>
/// <param name="pass">登陆口令</param>
/// <param name="mode">链接方式</param>
/// <param name="timeout">无响应时间(限时),单位:秒 (小于或等于0为不受时间限制)</param>
public FTP(string server, int port, string user, string pass, int mode, int timeout_sec)
{
this.server = server;
this.user = user;
this.pass = pass;
this.port = port;
passive_mode = mode <= 1 ? true : false;
main_sock = null;
main_ipEndPoint = null;
listening_sock = null;
data_sock = null;
data_ipEndPoint = null;
file = null;
bucket = "";
bytes_total = 0;
this.timeout = (timeout_sec <= 0) ? int.MaxValue : (timeout_sec * 1000); //无响应时间
messages = "";
errormessage = "";
}
#endregion
#region 属性
/// <summary>
/// 当前是否已连接
/// </summary>
public bool IsConnected
{
get
{
if (main_sock != null)
return main_sock.Connected;
return false;
}
}
/// <summary>
/// 当message缓冲区有数据则返回
/// </summary>
public bool MessagesAvailable
{
get
{
if (messages.Length > 0)
return true;
return false;
}
}
/// <summary>
/// 获取服务器状态返回信息, 并清空messages变量
/// </summary>
public string Messages
{
get
{
string tmp = messages;
messages = "";
return tmp;
}
}
/// <summary>
/// 最新指令发出后服务器的响应
/// </summary>
public string ResponseString
{
get
{
return responseStr;
}
}
/// <summary>
///在一次传输中,发送或接收的字节数
/// </summary>
public long BytesTotal
{
get
{
return bytes_total;
}
}
/// <summary>
///被下载或上传的文件大小,当文件大小无效时为0
/// </summary>
public long FileSize
{
get
{
return file_size;
}
}
/// <summary>
/// 链接模式:
/// true 被动模式 [默认]
/// false: 主动模式
/// </summary>
public bool PassiveMode
{
get
{
return passive_mode;
}
set
{
passive_mode = value;
}
}
#endregion
#region 操作
/// <summary>
/// 操作失败
/// </summary>
private void Fail()
{
Disconnect();
errormessage += responseStr;
//throw new Exception(responseStr);
}
/// <summary>
/// 下载文件类型
/// </summary>
/// <param name="mode">true:二进制文件 false:字符文件</param>
private void SetBinaryMode(bool mode)
{
if (mode)
SendCommand("TYPE I");
else
SendCommand("TYPE A");
ReadResponse();
if (response != 200)
Fail();
}
/// <summary>
/// 发送命令
/// </summary>
/// <param name="command"></param>
private void SendCommand(string command)
{
Byte[] cmd = Encoding.ASCII.GetBytes((command + "\r\n").ToCharArray());
if (command.Length > 3 && command.Substring(0, 4) == "PASS")
{
messages = "\rPASS xxx";
}
else
{
messages = "\r" + command;
}
try
{
main_sock.Send(cmd, cmd.Length, 0);
}
catch (Exception ex)
{
try
{
Disconnect();
errormessage += ex.Message;
return;
}
catch
{
main_sock.Close();
file.Close();
main_sock = null;
main_ipEndPoint = null;
file = null;
}
}
}
private void FillBucket()
{
Byte[] bytes = new Byte[512];
long bytesgot;
int msecs_passed = 0;
while (main_sock.Available < 1)
{
System.Threading.Thread.Sleep(50);
msecs_passed += 50;
//当等待时间到,则断开链接
if (msecs_passed > timeout)
{
Disconnect();
errormessage += "Timed out waiting on server to respond.";
return;
}
}
while (main_sock.Available > 0)
{
bytesgot = main_sock.Receive(bytes, 512, 0);
bucket += Encoding.ASCII.GetString(bytes, 0, (int)bytesgot);
System.Threading.Thread.Sleep(50);
}
}
private string GetLineFromBucket()
{
int i;
string buf = "";
if ((i = bucket.IndexOf('\n')) < 0)
{
while (i < 0)
{
FillBucket();
i = bucket.IndexOf('\n');
}
}
buf = bucket.Substring(0, i);
bucket = bucket.Substring(i + 1);
return buf;
}
/// <summary>
/// 返回服务器端返回信息
/// </summary>
private void ReadResponse()
{
string buf;
messages = "";
while (true)
{
buf = GetLineFromBucket();
if (Regex.Match(buf, "^[0-9]+ ").Success)
{
responseStr = buf;
response = int.Parse(buf.Substring(0, 3));
break;
}
else
messages += Regex.Replace(buf, "^[0-9]+-", "") + "\n";
}
}
/// <summary>
/// 打开数据套接字
/// </summary>
private void OpenDataSocket()
{
if (passive_mode)
{
string[] pasv;
string server;
int port;
Connect();
SendCommand("PASV");
ReadResponse();
if (response != 227)
Fail();
try
{
int i1, i2;
i1 = responseStr.IndexOf('(') + 1;
i2 = responseStr.IndexOf(')') - i1;
pasv = responseStr.Substring(i1, i2).Split(',');
}
catch (Exception)
{
Disconnect();
errormessage += "Malformed PASV response: " + responseStr;
return;
}
if (pasv.Length < 6)
{
Disconnect();
errormessage += "Malformed PASV response: " + responseStr;
return;
}
server = String.Format("{0}.{1}.{2}.{3}", pasv[0], pasv[1], pasv[2], pasv[3]);
port = (int.Parse(pasv[4]) << 8) + int.Parse(pasv[5]);
try
{
CloseDataSocket();
data_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//#if NET1
data_ipEndPoint = new IPEndPoint(Dns.GetHostByName(server).AddressList[0], port);
//#else
// data_ipEndPoint = new IPEndPoint(System.Net.Dns.GetHostEntry(server).AddressList[0], port);
//#endif
data_sock.Connect(data_ipEndPoint);
}
catch (Exception ex)
{
errormessage += "Failed to connect for data transfer: " + ex.Message;
return;
}
}
else
{
Connect();
try
{
CloseDataSocket();
listening_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 对于端口,则发送IP地址.下面则提取相应信息
string sLocAddr = main_sock.LocalEndPoint.ToString();
int ix = sLocAddr.IndexOf(':');
if (ix < 0)
{
errormessage += "Failed to parse the local address: " + sLocAddr;
return;
}
string sIPAddr = sLocAddr.Substring(0, ix);
// 系统自动绑定一个端口号(设置 port = 0)
System.Net.IPEndPoint localEP = new IPEndPoint(IPAddress.Parse(sIPAddr), 0);
listening_sock.Bind(localEP);
sLocAddr = listening_sock.LocalEndPoint.ToString();
ix = sLocAddr.IndexOf(':');
if (ix < 0)
{
errormessage += "Failed to parse the local address: " + sLocAddr;
}
int nPort = int.Parse(sLocAddr.Substring(ix + 1));
// 开始侦听链接请求
listening_sock.Listen(1);
string sPortCmd = string.Format("PORT {0},{1},{2}",
sIPAddr.Replace('.', ','),
nPort / 256, nPort % 256);
SendCommand(sPortCmd);
ReadResponse();
if (response != 200)
Fail();
}
catch (Exception ex)
{
errormessage += "Failed to connect for data transfer: " + ex.Message;
return;
}
}
}
private void ConnectDataSocket()
{
if (data_sock != null) // 已链接
return;
try
{
data_sock = listening_sock.Accept(); // Accept is blocking
listening_sock.Close();
listening_sock = null;
if (data_sock == null)
{
throw new Exception("Winsock error: " +
Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error()));
}
}
catch (Exception ex)
{
errormessage += "Failed to connect for data transfer: " + ex.Message;
}
}
本文转载自异步社区
原文链接:
- 点赞
- 收藏
- 关注作者
评论(0)