网络课程设计-MKFTP v1.0 Server + ClientBrower
目前只实现了课程设计要求的几个功能:
1. get remote-file [local-file] :从Server下载的一个文件
2. put local-file [remote-file] :传给Server一个文件
3. pwd :显示Server当前目录
4. dir :列出Server当前目录
5. cd directory :改变Server当前目录
6. ? [command] :显示所提供的命令
7. quit :退出返回
![]()
FtpServer.MainApp
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Net;
6
using System.Net.Sockets;
7
using System.Threading;
8![]()
9
namespace FtpServer
10![]()
![]()
{
11
public class MainApp
12![]()
{
13
public static string FtpRoot = @"E:\FTP";
14![]()
15
public static void getHelp()
16![]()
{
17
Console.WriteLine("Ftp help:");
18
Console.WriteLine("-r [path]\t:\tChange FTP Root");
19
Console.WriteLine("-? \t:\tGet Help");
20
}
21![]()
22
public static void Main(string[] args)
23![]()
{
24
for (int i = 0; i < args.Length; i++)
25![]()
{
26
switch (args[i])
27![]()
{
28
case "-r":
29
FtpRoot = args[i + 1];
30
break;
31
case "-?":
32
getHelp();
33
break;
34
default:
35
36
FtpRoot = Directory.GetCurrentDirectory();
37
break;
38
}
39
}
40
Console.WriteLine("FTP server Start");
41
//创建一个FTP对象
42
Ftp ftp = new Ftp();
43
//启动Ftp
44
if (ftp.Start() == false)
45![]()
{
46
Console.WriteLine("Failed to start FTP Server.");
47
}
48
}
49
}
50
}
51
![]()
FtpServer.SessionInfo
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Net;
6
using System.Net.Sockets;
7
using System.Threading;
8![]()
9
namespace FtpServer
10![]()
![]()
{
11
public class SessionInfo
12![]()
{
13
private bool _binary;
14![]()
15
public bool Binary
16![]()
{
17![]()
get
{ return _binary; }
18![]()
set
{ _binary = value; }
19
}
20
private bool _passive;
21![]()
22
public bool Passive
23![]()
{
24![]()
get
{ return _passive; }
25![]()
set
{ _passive = value; }
26
}
27
private string _ftpRoot;
28![]()
29
public string FtpRoot
30![]()
{
31![]()
get
{ return _ftpRoot; }
32![]()
set
{ _ftpRoot = value; }
33
}
34
private string _userName;
35![]()
36
public string UserName
37![]()
{
38![]()
get
{ return _userName; }
39![]()
set
{ _userName = value; }
40
}
41
private PassiveInfo _passiveInfo;
42![]()
43
public PassiveInfo PassiveInfo
44![]()
{
45![]()
get
{ return _passiveInfo; }
46![]()
set
{ _passiveInfo = value; }
47
}
48![]()
49
private IPEndPoint _remoteEP;
50![]()
51
public IPEndPoint RemoteEP
52![]()
{
53![]()
get
{ return _remoteEP; }
54![]()
set
{ _remoteEP = value; }
55
}
56![]()
57
private string _username = "";
58![]()
59
public string Username
60![]()
{
61![]()
get
{ return _username; }
62![]()
set
{ _username = value; }
63
}
64
private string _password = "";
65![]()
66
public string Password
67![]()
{
68![]()
get
{ return _password; }
69![]()
set
{ _password = value; }
70
}
71
72
public SessionInfo()
73![]()
{
74
_binary = true;
75
_passive = true;
76
_ftpRoot = MainApp.FtpRoot;
77
_userName = "";
78
_passiveInfo = new PassiveInfo();
79
_remoteEP = null;
80
}
81
}
82![]()
83
public class PassiveInfo
84![]()
{
85
private IPHostEntry _IPHostEntry;
86![]()
87
public IPHostEntry IPHostEntry
88![]()
{
89![]()
get
{ return _IPHostEntry; }
90![]()
set
{ _IPHostEntry = value; }
91
}
92
private TcpListener _tcpListener;
93![]()
94
public TcpListener TcpListener
95![]()
{
96![]()
get
{ return _tcpListener; }
97![]()
set
{ _tcpListener = value; }
98
}
99
private IPEndPoint _remoteEP;
100![]()
101
public IPEndPoint RemoteEP
102![]()
{
103![]()
get
{ return _remoteEP; }
104![]()
set
{ _remoteEP = value; }
105
}
106![]()
107
public PassiveInfo()
108![]()
{
109
_IPHostEntry = null;
110
_tcpListener = null;
111
_remoteEP = null;
112
}
113![]()
114
public PassiveInfo(IPHostEntry host, TcpListener listener, IPEndPoint remoteEP)
115![]()
{
116
_IPHostEntry = host;
117
_tcpListener = listener;
118
_remoteEP = remoteEP;
119
}
120
}
121
}
122
![]()
FtpServer.Ftp
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Net;
6
using System.Net.Sockets;
7
using System.Threading;
8
using System.Globalization;
9![]()
10
namespace FtpServer
11![]()
![]()
{
12
public class Ftp
13![]()
{
14
private TcpListener _tcpListener;
15
private Socket _socket;
16
private IPHostEntry _IPHostEntry;
17
private IPEndPoint _IPEndPoint;
18![]()
19
public Ftp()
20![]()
{
21
_IPHostEntry = Dns.GetHostEntry(Dns.GetHostName());
22
_IPEndPoint = new IPEndPoint(_IPHostEntry.AddressList[0], 21);
23
_tcpListener = new TcpListener(_IPEndPoint);
24
}
25![]()
26
public bool Start()
27![]()
{
28
try
29![]()
{
30
_tcpListener.Start();
31
while (true)
32![]()
{
33
//接收到客户端的一个连接请求,返回一个Socket响应它,采用多线程方式,支持多用户同时访问
34
//此Socket是处理用户的控制连接
35
_socket = _tcpListener.AcceptSocket();
36
Thread client = new Thread(new ThreadStart(ServerConnection));
37
client.Start();
38
}
39
}
40
catch (SocketException se)
41![]()
{
42
Console.WriteLine("Error: {0}", se.Message);
43
return false;
44
}
45
}
46![]()
47
public void Reply(Socket socket, int responseCode, string message)
48![]()
{
49
try
50![]()
{
51
string response = responseCode + " " + message + "\r\n";
52
byte[] datas = GetBytes(response);
53
socket.Send(datas);
54
}
55
catch (Exception e)
56![]()
{
57
Console.WriteLine(e.Message);
58
}
59
}
60![]()
61
private byte[] GetBytes(string response)
62![]()
{
63
return GetBytes(response, Encoding.Default);
64
}
65![]()
66
private byte[] GetBytes(string response, Encoding encoder)
67![]()
{
68
return encoder.GetBytes(response);
69
}
70![]()
71
private string GetString(byte[] datas, int offset, int size)
72![]()
{
73
return GetString(datas, offset, size, Encoding.Default);
74
}
75![]()
76
private string GetString(byte[] datas, int offset, int size, Encoding encoder)
77![]()
{
78
return encoder.GetString(datas, offset, size);
79
}
80![]()
81![]()
/**//// <summary>
82
/// 处理一个连接请求
83
/// </summary>
84
private void ServerConnection()
85![]()
{
86
//这里需要互斥访问??
87
Socket socket = _socket;
88
//建立一个新会话
89
SessionInfo session = new SessionInfo();
90
session.RemoteEP = (IPEndPoint)socket.RemoteEndPoint;
91
//显示服务器信息
92
string message = "Welcome to MK FTP Server v1.0, Base on .NET Framework 2.0.";
93
Reply(socket, 220, message);
94![]()
95
//分析用户命令
96
CheckCommand(socket, session);
97
}
98![]()
99
private void CheckCommand(Socket socket, SessionInfo session)
100![]()
{
101
try
102![]()
{
103
//循环执行用户命令
104
while (true)
105![]()
{
106
byte[] buffer = new byte[256];
107
//接收命令
108
int dataSize = socket.Receive(buffer);
109
string cmd = GetString(buffer, 0, dataSize).Replace("\r\n", "");
110
string command = "";
111
string parameter = "";
112
if (cmd.Length == 3)
113
command = cmd;
114
else
115
command = cmd.Substring(0, 3);
116
string paras = "";
117
command = command.ToUpper();
118
if (command != "CWD" && command != "PWD")
119![]()
{
120
command = cmd.Substring(0, 4).ToUpper();
121
if (cmd.Length > 4)
122
parameter = cmd.Substring(5);
123
}
124
else
125![]()
{
126
if (cmd.Length > 3)
127![]()
{
128
parameter = cmd.Substring(4);
129
}
130
}
131
//for (int i = 0; i < 4; i++)
132
//{
133
// //不是回车换行符
134
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)
135
// {
136
// command += (char)buffer[i];
137
// }
138
//}
139
//if (command != "CWD" && command != "PWD")
140
//{
141
// for (int i = 5; i < buffer.Length; i++)
142
// {
143
// //不是回车换行符
144
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)
145
// {
146
// parameter += (char)buffer[i];
147
// }
148
// }
149
//}
150
//else
151
//{
152
// for (int i = 4; i < buffer.Length; i++)
153
// {
154
// //不是回车换行符
155
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)
156
// {
157
// parameter += (char)buffer[i];
158
// }
159
// }
160
//}
161
//parameter = parameter.Trim();
162
System.Console.WriteLine("From {0} : {1} {2}", socket.RemoteEndPoint, command, parameter);
163![]()
164
//FTP命令格式:前4位为命令类型,后面为命令参数
165
switch (command)
166![]()
{
167
//用户
168
case "USER":
169
session.UserName = parameter;
170
Reply(socket, 331, "User name okey, need password.");
171
break;
172
//密码
173
case "PASS":
174
session.Password = parameter;
175
AuthenticateUser(socket, session.UserName, session.Password);
176
break;
177
//EPSV 扩展被动模式
178
case "EPSV":
179
Reply(socket, 522, "Extended Passive Mode not supported.");
180
break;
181
//被动模式
182
case "PASV":
183
session.Passive = true;
184
ProcessPassiveCommand(socket, parameter, session);
185
break;
186
//设定主动模式的数据连接端口
187
case "PORT":
188
session.Passive = false;
189
ProcessPortCommand(socket, parameter, session);
190
break;
191
//文件及子目录列表
192
case "LIST":
193
ProcessListCommand(socket, parameter, session);
194
break;
195
//发送客户端下载的文件
196
case "RETR":
197
ProcessRetreiveCommand(socket, parameter, session);
198
break;
199
//名字系统类型
200
case "SYST":
201
Reply(socket, 215, System.Environment.OSVersion.VersionString);
202
break;
203
//上传文件
204
case "STOR":
205
ProcessStoreCommand(socket, parameter, session);
206
break;
207
//改变工作目录
208
case "CWD":
209
ProcessCWDCommand(socket, parameter, session);
210
break;
211
//当前目录
212
case "PWD":
213
ProcessPWDCommand(socket, parameter, session);
214
break;
215
//传输模式
216
case "TYPE":
217
switch (parameter)
218![]()
{
219
case "I":
220
session.Binary = true;
221
Reply(socket, 200, "Type set to I.");
222
break;
223
case "A":
224
session.Binary = false;
225
Reply(socket, 200, "Type set to A.");
226
break;
227
default:
228
Reply(socket, 200, "Type not change.");
229
break;
230
}
231
break;
232
//退出
233
case "QUIT":
234
Reply(socket, 221, "Goodbye!.");
235
socket.Close();
236
return;
237
default:
238
Reply(socket, 502, "'" + command + "': not implemented.");
239
break;
240
}
241
}
242
}
243
catch (Exception e)
244![]()
{
245
Console.WriteLine(e.Message);
246
}
247
}
248![]()
249
private void ProcessPWDCommand(Socket socket, string parameter, SessionInfo session)
250![]()
{
251
Reply(socket, 257, "\"" + session.FtpRoot + "\" is current directory.");
252
}
253![]()
254
private void ProcessCWDCommand(Socket socket, string parameter, SessionInfo session)
255![]()
{
256
if (parameter.IndexOf("\\") > 0 && parameter.IndexOf(":") > 0)
257![]()
{
258
session.FtpRoot = parameter;
259
}
260
else
261![]()
{
262
session.FtpRoot += @"\" + parameter;
263
}
264
265
DirectoryInfo dir = new DirectoryInfo(session.FtpRoot);
266
if (!dir.Exists)
267![]()
{
268
Reply(socket, 550, dir.FullName + ": No such directory.");
269
return;
270
}
271
Reply(socket, 250, "Directory changed to "+dir.FullName);
272
}
273![]()
274
private void ProcessStoreCommand(Socket socket, string parameter, SessionInfo session)
275![]()
{
276
try
277![]()
{
278
string file = session.FtpRoot + @"\" + parameter;
279
FileStream fs = new FileStream(file, FileMode.Create);
280![]()
281
byte[] buffer = new byte[1024];
282![]()
283
int dataSize = 0;
284![]()
285
if (session.Binary)
286![]()
{
287
Reply(socket, 150, "Opening BINARY mode data connection for " + parameter);
288
BinaryWriter bw = new BinaryWriter(fs);
289
Socket binarySocket;
290
if (session.Passive)
291![]()
{
292
binarySocket = session.PassiveInfo.TcpListener.AcceptSocket();
293![]()
294
}
295
else
296![]()
{
297
binarySocket = new Socket(AddressFamily.InterNetwork,
298
SocketType.Stream, ProtocolType.Tcp);
299
binarySocket.Bind(new IPEndPoint(_IPEndPoint.Address, 0));
300
binarySocket.Connect(session.RemoteEP);
301
}
302
while ((dataSize = binarySocket.Receive(buffer)) > 0)
303![]()
{
304
bw.Write(buffer, 0, dataSize);
305
}
306
bw.Close();
307
binarySocket.Close();
308
}
309
else
310![]()
{
311
//FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);
312
//Reply(socket, 150, "Opening ASCII mode data connection for " + parameter
313
// + " (" + fileInfo.Length + " Bytes).");
314
//StreamReader sr = new StreamReader(fs);
315
//if (session.Passive)
316
//{
317
// SendOverPassiveDataConnection(GetBytes(sr.ReadToEnd(), Encoding.UTF8), session);
318![]()
319
//}
320
//else
321
//{
322
// SendOverDataConnection(GetBytes(sr.ReadToEnd(), Encoding.UTF8), session);
323
//}
324
//sr.Close();
325
//fs.Close();
326
}
327![]()
328
Reply(socket, 226, "Transfer Complete");
329![]()
330
}
331
catch (Exception e)
332![]()
{
333
Console.WriteLine(e.Message);
334
}
335
}
336![]()
337
private void ProcessRetreiveCommand(Socket socket, string parameter, SessionInfo session)
338![]()
{
339
try
340![]()
{
341
string file = session.FtpRoot + @"\" + parameter;
342
FileInfo fileInfo =new FileInfo(file);
343
if (!fileInfo.Exists)
344![]()
{
345
Reply(socket, 550, fileInfo.FullName + ": No such file.");
346
return;
347
}
348
if (session.Binary)
349![]()
{
350
Reply(socket, 150, "Opening BINARY mode data connection for " + parameter
351
+ " (" + fileInfo.Length + " Bytes)");
352
//BinaryReader br = new BinaryReader(fs);
353
Socket binarySocket;
354
if (session.Passive)
355![]()
{
356
binarySocket = session.PassiveInfo.TcpListener.AcceptSocket();
357
}
358
else
359![]()
{
360
binarySocket = new Socket(AddressFamily.InterNetwork,
361
SocketType.Stream, ProtocolType.Tcp);
362
binarySocket.Bind(new IPEndPoint(_IPEndPoint.Address, 0));
363
binarySocket.Connect(session.RemoteEP);
364
}
365
//while (br.PeekChar() > -1)
366
//{
367
// binarySocket.Send(br.ReadBytes(10240));
368
// //binarySocket.
369
//}
370
//br.Close();
371
binarySocket.SendFile(fileInfo.FullName);
372
binarySocket.Close();
373
}
374
else
375![]()
{
376
FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);
377
Reply(socket, 150, "Opening ASCII mode data connection for " + parameter
378
+ " (" + fileInfo.Length + " Bytes).");
379
StreamReader sr = new StreamReader(fs);
380
if (session.Passive)
381![]()
{
382
SendOverPassiveDataConnection(GetBytes(sr.ReadToEnd()), session);
383![]()
384
}
385
else
386![]()
{
387
SendOverDataConnection(GetBytes(sr.ReadToEnd()), session);
388
}
389
sr.Close();
390
fs.Close();
391
}
392
393
Reply(socket, 200, "Transfer Complete");
394
395
}
396
catch (Exception e)
397![]()
{
398
Console.WriteLine(e.Message);
399
}
400
}
401![]()
402
private void ProcessListCommand(Socket socket, string parameter, SessionInfo session)
403![]()
{
404
DirectoryInfo curDir = new DirectoryInfo(session.FtpRoot);
405
DirectoryInfo[] dirInfoList = curDir.GetDirectories();
406
FileInfo[] fileSysInfoList = curDir.GetFiles();
407![]()
408
const string s_dir = "\t";//"┼ <DIR> ";
409
const string s_file = "";// "├ ";
410
const string s_d_right = "drw-rw-rw-";
411
const string s_f_right = "_rw-rw-rw-";
412
const string s_1 = " ";
413
const string s_3 = " ";
414
const string s_7 = " ";
415
const string s_10 = " ";
416
StringBuilder sb = new StringBuilder();
417
foreach (DirectoryInfo dir in dirInfoList)
418![]()
{
419
//sb.Append(s_d_right + s_1 + "1 user" + s_1 + "group" + s_1 + 0 + s_1 + dir.LastWriteTime + s_1 + dir.Name);
420
//sb.Append("\r\n");
421
GetFormatRow(sb, s_d_right, 0, dir.LastWriteTime, dir.Name);
422
}
423![]()
424
foreach (FileInfo file in fileSysInfoList)
425![]()
{
426
//sb.Append(s_f_right + s_1 + "1 user" + s_1 + "group" + s_1 + file.Length + s_1 + file.LastWriteTime + s_1 + file.Name);
427
//sb.Append("\r\n");
428
GetFormatRow(sb, s_f_right, file.Length, file.LastWriteTime, file.Name);
429
}
430![]()
431
Reply(socket, 150, "Opening ASCII mode data connection for /bin/ls.");
432
if (session.Passive)
433![]()
{
434
SendOverPassiveDataConnection(GetBytes(sb.ToString()), session);
435
}
436
else
437![]()
{
438
SendOverDataConnection(GetBytes(sb.ToString()), session);
439
}
440
Console.WriteLine("Listed.");
441
//socket.
442
Reply(socket, 226, "Transfer complete.");
443![]()
444
}
445![]()
446
private string GetFormatRow(StringBuilder sb, string right, Int64 size, DateTime date, string name)
447![]()
{
448
const string s_1 = " ";
449
sb.Append(right + s_1);
450
sb.Append("user group ");
451
for (int i = size.ToString().Length; i < 12; i++)
452![]()
{
453
sb.Append(s_1);
454
}
455
sb.Append(size + s_1);
456
sb.Append(date.ToString("MMM d hh:ss ", DateTimeFormatInfo.InvariantInfo));
457
sb.Append(name + "\r\n");
458
return sb.ToString();
459
}
460![]()
461![]()
/**//// <summary>
462
/// 主动模式下传输数据
463
/// </summary>
464
/// <param name="p"></param>
465
private bool SendOverDataConnection(byte[] datas, SessionInfo session)
466![]()
{
467
try
468![]()
{
469
Console.WriteLine("Connecting Client: {0}
", session.RemoteEP);
470
TcpClient tcpClient = new TcpClient();
471
tcpClient.Connect(session.RemoteEP);
472
//Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
473
//IPEndPoint localEP = new IPEndPoint(_IPEndPoint.Address, 0);
474
//s.Bind(localEP);
475
//s.Connect(session.RemoteEP);
476
//s.Send(datas);
477![]()
478
Console.WriteLine("Connected, Sending data
");
479
NetworkStream ns = tcpClient.GetStream();
480
ns.Write(datas, 0, datas.Length);
481
Console.WriteLine("Sended.");
482
//s.Close();
483
ns.Close();
484
tcpClient.Close();
485
}
486
catch (SocketException se)
487![]()
{
488
Console.WriteLine(se.Message);
489
return false;
490
}
491
return true;
492
}
493![]()
494
private bool SendOverPassiveDataConnection(byte[] datas, SessionInfo session)
495![]()
{
496
try
497![]()
{
498
Console.WriteLine("Connecting Client: {0}
", session.RemoteEP);
499
TcpClient tcpClient = session.PassiveInfo.TcpListener.AcceptTcpClient();
500![]()
501
Console.WriteLine("Connected, Sending data
");
502
NetworkStream ns = tcpClient.GetStream();
503
ns.Write(datas, 0, datas.Length);
504
//int d=ns.DataAvailable
505
Thread.Sleep(100); //防止发送太快,客户端接收错误
506
Console.WriteLine("Sended.");
507
//s.Close();
508
ns.Close();
509
tcpClient.Close();
510
}
511
catch (SocketException se)
512![]()
{
513
Console.WriteLine(se.Message);
514
return false;
515
}
516
return true;
517
}
518![]()
519![]()
/**//// <summary>
520
/// 用户指定端口,用于主动传输模式。每次传输前,用户都会设置端口
521
/// </summary>
522
/// <param name="socket"></param>
523
/// <param name="parameter"></param>
524
private void ProcessPortCommand(Socket socket, string parameter, SessionInfo session)
525![]()
{
526
string[] endPoints = parameter.Split(',');
527
string remoteIP = endPoints[0] + "." + endPoints[1] + "."
528
+ endPoints[2] + "." + endPoints[3];
529
//int port = Convert.ToInt32(endPoints[4] + endPoints[5]);
530
//endp[4] X 256 + endp[5];
531
int port = (Convert.ToInt32(endPoints[4]) * 256) + (int.Parse(endPoints[5]));
532
IPAddress ip = IPAddress.Parse(remoteIP);
533
IPEndPoint remoteEP = new IPEndPoint(ip, port);
534![]()
535
session.RemoteEP = remoteEP;
536
Reply(socket, 200, "PORT Command successful.");
537
Console.WriteLine("PORT SET");
538
}
539![]()
540
//响应被动模式命令
541
private void ProcessPassiveCommand(Socket socket, string parameter, SessionInfo session)
542![]()
{
543
//创建一个空闲EP
544
IPEndPoint hostEP = new IPEndPoint(_IPHostEntry.AddressList[0], 0);
545
TcpListener tcpListener = new TcpListener(hostEP);
546
session.PassiveInfo.IPHostEntry = _IPHostEntry;
547
session.PassiveInfo.TcpListener = tcpListener;
548
//session.PassiveInfo.RemoteEP = hostEP;
549
session.Passive = true;
550
session.PassiveInfo.TcpListener.Start();
551![]()
552
IPEndPoint localEP = (IPEndPoint)tcpListener.LocalEndpoint;
553
string ip = localEP.Address.ToString().Replace(".", ",");
554
int p1 = localEP.Port / 256;
555
int p2 = localEP.Port % 256;
556![]()
557
Reply(socket, 227, "Entering Passive Mode (" + ip + "," + p1 + "," + p2 + ")");
558![]()
559
}
560![]()
561
private void AuthenticateUser(Socket socket, string username, string password)
562![]()
{
563
//do Authenticate user name and password
564
Reply(socket, 230, "User logged in, proceed.");
565
}
566
}
567![]()
568
569
}
570
![]()
FtpClient.ClientMainApp
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Net;
6
using System.Net.Sockets;
7
using System.Threading;
8
using System.Globalization;
9![]()
10
namespace FtpClient
11![]()
![]()
{
12
class ClientMainApp
13![]()
{
14
static void Main(string[] args)
15![]()
{
16
try
17![]()
{
18
IPHostEntry server;
19
try
20![]()
{
21
server = Dns.GetHostEntry(IPAddress.Parse(args[0]));
22
}
23
catch
24![]()
{
25
server = Dns.GetHostEntry(args[0]);
26
}
27![]()
28
29![]()
30
IPEndPoint serverEP = new IPEndPoint(server.AddressList[0], 21);
31![]()
32
FtpViewer browser = new FtpViewer(serverEP);
33
browser.Start();
34![]()
35![]()
/**/////登录FTP Server
36
//Console.WriteLine("USER anonymous");
37
//browser.Excute("USER anonymous");
38
//Console.WriteLine("PASS 1111");
39
//browser.Excute("PASS 1111");
40
//Console.WriteLine("SYST");
41
//browser.Excute("SYST");
42
//Console.WriteLine("PWD");
43
//browser.Excute("PWD");
44
//Console.WriteLine("TYPE A");
45
//browser.Excute("TYPE A");
46
//Console.WriteLine("PORT");
47
//browser.Excute("PORT");
48
//Console.WriteLine("LIST");
49
//browser.Excute("LIST");
50
//browser.ExcuteCommand("dir");
51![]()
52![]()
53![]()
54![]()
/**///////下载文件
55
////Console.WriteLine("TYPE I");
56
////browser.Excute("TYPE I");
57
////Console.WriteLine("PASV");
58
////browser.Excute("PASV");
59
////Console.WriteLine("RETR picture.JPG");
60
////browser.Excute("RETR picture.JPG");
61
//browser.ExcuteCommand("get picture.JPG");
62![]()
63![]()
/**///////更改目录
64
////Console.WriteLine("CWD files");
65
////browser.Excute("CWD files");
66
////Console.WriteLine("PWD");
67
////browser.Excute("PWD");
68
////Console.WriteLine("PASV");
69
////browser.Excute("PASV");
70
////Console.WriteLine("LIST -al");
71
////browser.Excute("LIST -al");
72
//browser.ExcuteCommand("cd files");
73![]()
74![]()
/**///////上传文件
75
////Console.WriteLine("TYPE I");
76
////browser.Excute("TYPE I");
77
////Console.WriteLine("PASV");
78
////browser.Excute("PASV");
79
////Console.WriteLine("STOR network4.rar");
80
////browser.Excute("STOR network4.rar");
81
//browser.ExcuteCommand("put network4.rar");
82![]()
83![]()
/**/////Console.WriteLine("RETR testFiles222.txt");
84
////browser.Excute("RETR testFiles222.txt");
85
////Console.WriteLine("RETR testFiles1.txt");
86
////browser.Excute("RETR testFiles1.txt");
87
////Console.WriteLine("RETR picture.JPG");
88
////browser.Excute("RETR picture.JPG");
89
////Console.WriteLine("RETR network4.rar");
90
////browser.Excute("RETR network4.rar");
91
////Console.WriteLine("R2TR sdlfjldjgsd");
92
////browser.Excute("R2TR sdlfjldjgsd");
93
////Console.WriteLine("CWD files");
94
////browser.Excute("CWD files");
95
////Console.WriteLine("RETR files_ftp应答码.txt");
96
////browser.Excute("RETR files_ftp应答码.txt");
97![]()
98
////browser.ExcuteCommand("quit");
99
//browser.ExcuteCommand("user anonymous 123");
100
while (browser.IsRunning)
101![]()
{
102
Console.Write("ftp> ");
103
string cmd = Console.ReadLine();
104
browser.ExcuteCommand(cmd);
105
}
106
}
107
catch (Exception e)
108![]()
{
109
Console.WriteLine(e.Message);
110
}
111
//Console.Read();
112
}
113![]()
114
115
}
116
}
117
![]()
FtpClient.ControlInfo
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4![]()
5
namespace FtpClient
6![]()
![]()
{
7
public class ControlInfo
8![]()
{
9
private string _sendCommand;
10![]()
11
public string SendCommand
12![]()
{
13![]()
get
{ return _sendCommand; }
14![]()
set
{ _sendCommand = value; }
15
}
16![]()
17
private string _command;
18![]()
19
public string Command
20![]()
{
21![]()
get
{ return _command; }
22![]()
set
{ _command = value; }
23
}
24
private string _parameter;
25![]()
26
public string Parameter
27![]()
{
28![]()
get
{ return _parameter; }
29![]()
set
{ _parameter = value; }
30
}
31![]()
32
private string _parameter2 = "";
33![]()
34
public string Parameter2
35![]()
{
36![]()
get
{ return _parameter2; }
37![]()
set
{ _parameter2 = value; }
38
}
39![]()
40
private int _successCode;
41![]()
42
public int SuccessCode
43![]()
{
44![]()
get
{ return _successCode; }
45![]()
set
{ _successCode = value; }
46
}
47
private int _returnCode;
48![]()
49
public int ReturnCode
50![]()
{
51![]()
get
{ return _returnCode; }
52![]()
set
{ _returnCode = value; }
53
}
54
private string _message;
55![]()
56
public string Message
57![]()
{
58![]()
get
{ return _message; }
59![]()
set
{ _message = value; }
60
}
61![]()
62
private string _returnResult;
63![]()
64
public string ReturnResult
65![]()
{
66![]()
get
{ return _returnResult; }
67![]()
set
{ _returnResult = value; }
68
}
69![]()
70
public ControlInfo()
71![]()
{
72
_successCode = 220;
73
}
74![]()
75
public ControlInfo(string cmd, string paras)
76![]()
{
77
_command = cmd;
78
_parameter = paras;
79
_successCode = GetSuccessCode(cmd);
80
}
81![]()
82
public ControlInfo(string sendCommand, string cmd, string paras)
83![]()
{
84
_sendCommand = sendCommand;
85
_command = cmd;
86
_parameter = paras;
87
_successCode = GetSuccessCode(cmd);
88
}
89![]()
90
public ControlInfo(string sendCommand, string cmd, string paras, string paras2)
91![]()
{
92
_sendCommand = sendCommand;
93
_command = cmd;
94
_parameter = paras;
95
_parameter2 = paras2;
96
_successCode = GetSuccessCode(cmd);
97
}
98![]()
99
//指示此初操作命令是否成功
100
public bool Success
101![]()
{
102
get
103![]()
{
104
return _returnCode == _successCode;
105
}
106
}
107![]()
108![]()
/**//// <summary>
109
/// 获取带参数的命令
110
/// </summary>
111
/// <returns></returns>
112
public string GetCommand()
113![]()
{
114
return _command + (_parameter.Length > 0 ? " " + _parameter : "") + "\r\n";
115
}
116![]()
117![]()
/**//// <summary>
118
/// 获取指定命令成功执行希望得到响应的代码
119
/// </summary>
120
/// <param name="command"></param>
121
/// <returns></returns>
122
public static int GetSuccessCode(string command)
123![]()
{
124
switch (command)
125![]()
{
126
//用户
127
case "USER":
128
return 331;
129
//密码
130
case "PASS":
131
return 230;
132
//EPSV
133
case "EPSV":
134
return 522;
135
//被动模式
136
case "PASV":
137
return 227;
138
//设定主动模式的数据连接端口
139
case "PORT":
140
return 200;
141
//文件及子目录列表
142
case "LIST":
143
return 150;
144
//发送客户端下载的文件
145
case "RETR":
146
return 150;
147
//名字系统类型
148
case "SYST":
149
return 215;
150
//上传文件
151
case "STOR":
152
return 150;
153
//改变工作目录
154
case "CWD":
155
return 250;
156
//当前目录
157
case "PWD":
158
return 257;
159
//传输模式
160
case "TYPE":
161
return 200;
162
default:
163
return 0;
164
}
165
}
166![]()
167
public static ControlInfo Create(string command)
168![]()
{
169
string cmd = "";
170
if (command.Length == 3)
171
cmd = command;
172
else
173
cmd = command.Substring(0, 3);
174
string paras = "";
175
cmd = cmd.ToUpper();
176
if (cmd != "CWD" && cmd != "PWD")
177![]()
{
178
cmd = command.Substring(0, 4).ToUpper();
179
if (command.Length > 4)
180
paras = command.Substring(5);
181
}
182
else
183![]()
{
184
if (command.Length > 3)
185![]()
{
186
paras = command.Substring(4);
187
}
188
}
189
if (paras.IndexOf(" ") > 0)
190![]()
{
191
int index = paras.IndexOf(" ");
192
string paras2 = paras.Substring(index + 1);
193
paras = paras.Substring(0, index);
194
ControlInfo cInfo2 = new ControlInfo(command, cmd, paras, paras2);
195
return cInfo2;
196
}
197
ControlInfo cInfo = new ControlInfo(command, cmd, paras);
198
return cInfo;
199
}
200
}
201
}
202
![]()
FtpClient.FtpViewer
1
using System;
2
using System.Collections.Generic;
3
using System.Text;
4
using System.IO;
5
using System.Net;
6
using System.Net.Sockets;
7
using System.Threading;
8
using System.Globalization;
9
using System.Collections;
10![]()
11
namespace FtpClient
12![]()
![]()
{
13
public class FtpViewer
14![]()
{
15
private TcpClient _commandControler;
16
private TcpListener _listener;
17
private TcpClient _dataControler;
18
private IPEndPoint _serverEndPoint;
19
private IPEndPoint _transferEndPoint;
20
private IPAddress _clientIP;
21
private string _username;
22
private string _password;
23
private string _currentDir;
24
private string _serverDir = @"\";
25
private bool _isPassive = true; //默认被动模式,采用二进制模式传输数据
26
private bool _isBinary = true;
27
private bool _isRunning = false;
28![]()
29
public bool IsRunning
30![]()
{
31![]()
get
{ return _isRunning; }
32![]()
set
{ _isRunning = value; }
33
}
34![]()
35
public FtpViewer()
36![]()
{
37
38
}
39![]()
40
public FtpViewer(IPEndPoint serverEndPoint)
41![]()
{
42
_clientIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];
43
_serverEndPoint = serverEndPoint;
44
_commandControler = new TcpClient();
45
_currentDir = System.Environment.CurrentDirectory;
46
}
47![]()
48
public void SetBinaryMode(bool isBinary)
49![]()
{
50
if (isBinary != _isBinary)
51![]()
{
52
_isBinary = isBinary;
53
if (isBinary)
54![]()
{
55
Excute("TYPE I");
56
}
57
else
58![]()
{
59
Excute("TYPE A");
60
}
61
}
62
}
63![]()
64
public bool Start()
65![]()
{
66
_commandControler.Connect(_serverEndPoint);
67
ControlInfo controlInfo = new ControlInfo();
68
ReadReply(controlInfo);
69
Display(controlInfo.ReturnResult);
70![]()
71
DisplayCommand("User (" + _serverEndPoint.ToString() + ":) ");
72
Login(Console.ReadLine());
73![]()
74
_isRunning = true;
75
return true;
76
}
77![]()
78
public void Close()
79![]()
{
80
if (_commandControler != null)
81![]()
{
82
_commandControler.Close();
83
_commandControler = null;
84
}
85
if (_dataControler != null)
86![]()
{
87
_dataControler.Close();
88
_dataControler = null;
89
}
90
_isRunning = false;
91
}
92![]()
93
public bool ReadReply(ControlInfo controlInfo)
94![]()
{
95
try
96![]()
{
97
NetworkStream ns = _commandControler.GetStream();
98![]()
99
byte[] buffer = new byte[_commandControler.ReceiveBufferSize];
100
int dataSize = ns.Read(buffer, 0, buffer.Length);
101
string result = GetString(buffer, 0, dataSize);
102![]()
103
if (result.Length == 0)
104![]()
{
105
controlInfo.ReturnCode = 0;
106
controlInfo.Message = "";
107
controlInfo.ReturnResult = "";
108
return true;
109
}
110![]()
111
controlInfo.ReturnCode = Convert.ToInt32(result.Substring(0, 3));
112
controlInfo.Message = result.Substring(4);
113
controlInfo.ReturnResult = result;
114![]()
115
return true;
116
}
117
catch(Exception e)
118![]()
{
119
controlInfo.ReturnCode = 0;
120
controlInfo.Message = "";
121
controlInfo.ReturnResult = "";
122
DisplayLocalMessage(e.Message);
123
return false;
124
}
125
}
126![]()
127
public bool ReceiveData(ControlInfo controlInfo)
128![]()
{
129
InitDataControler();
130![]()
131
Send(controlInfo);
132
ReadReply(controlInfo);
133
Display(controlInfo.ReturnResult);
134![]()
135
if (!controlInfo.Success)
136![]()
{
137
Display( controlInfo.Parameter + " 传输失败!\n");
138
return false;
139
}
140
try
141![]()
{
142
143
int startTime = Environment.TickCount;
144![]()
145
NetworkStream ns = _dataControler.GetStream();
146
string filename = controlInfo.Parameter2.Length > 0 ? controlInfo.Parameter2 : controlInfo.Parameter;
147![]()
148
FileStream fs = new FileStream(_currentDir + @"\" + filename, FileMode.Create);
149
Int64 totalSize = 0;
150
if (_isBinary)
151![]()
{
152
byte[] buffer = new byte[1024];
153![]()
154
int dataSize = 0;
155![]()
156
BinaryWriter bw = new BinaryWriter(fs);
157![]()
158
while ((dataSize = ns.Read(buffer, 0, buffer.Length)) > 0)
159![]()
{
160
totalSize += dataSize;
161
bw.Write(buffer, 0, dataSize);
162
}
163![]()
164
bw.Close();
165
}
166
else
167![]()
{
168
//ArrayList datas = new ArrayList();
169
//StreamWriter sw
170
//while ((dataSize = ns.Read(buffer, 0, buffer.Length)) > 0)
171
//{
172
// //sw.Write(Encoding.UTF8.GetChars(buffer, 0, dataSize),
173
// //0, dataSize);
174
//}
175![]()
176
//StreamWriter sw = new StreamWriter(fs);
177
//sw.Write(Encoding.UTF8.GetString(buffer, 0, dataSize));
178
//Display("已传送 " + controlInfo.Parameter + " " + fs.Length + " bytes. \n");
179
//sw.Close();
180
}
181![]()
182
fs.Close();
183
ns.Close();
184
_dataControler.Close();
185
ReadReply(controlInfo);
186
Display(controlInfo.ReturnResult);
187
double useTime = GetUseTime(startTime, Environment.TickCount);
188
double speed = totalSize / useTime;
189![]()
190
Display("已传送 " + filename + " " + totalSize + " bytes, use time " +
191
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\n");
192![]()
193
return true;
194
}
195
catch (Exception e)
196![]()
{
197
DisplayLocalMessage(e.Message);
198
return false;
199
}
200
}
201![]()
202
private void InitDataControler()
203![]()
{
204
if (!_isPassive) //主动模式,等待Server的连接请求
205![]()
{
206
_dataControler = _listener.AcceptTcpClient();
207
}
208
else
209![]()
{
210
DisplayLocalMessage("正打开数据连接 IP: " + _transferEndPoint.ToString() + "\n");
211
_dataControler = new TcpClient();
212
_dataControler.Connect(_transferEndPoint);
213
}
214
}
215![]()
216
public bool ReceiveList(ControlInfo controlInfo)
217![]()
{
218
InitDataControler();
219![]()
220
Send(controlInfo);
221
ReadReply(controlInfo);
222
Display(controlInfo.ReturnResult);
223![]()
224
if (!controlInfo.Success)
225![]()
{
226
Display(controlInfo.Parameter + " 传输失败!\n");
227
return false;
228
}
229
try
230![]()
{
231
int startTime = Environment.TickCount;
232
NetworkStream ns = _dataControler.GetStream();
233
byte[] buffer = new byte[_dataControler.ReceiveBufferSize];
234
int totalSize = 0;
235
int dataSize = 0;
236
StringBuilder sb = new StringBuilder();
237![]()
238![]()
239
while ((dataSize = ns.Read(buffer, 0, _dataControler.ReceiveBufferSize)) > 0)
240![]()
{
241
sb.Append(GetString(buffer, 0, dataSize));
242
totalSize += dataSize;
243
}
244
double useTime = GetUseTime(startTime, Environment.TickCount);
245
double speed = totalSize / useTime;
246
if (controlInfo.Parameter.Length == 0)
247![]()
{
248
Display(sb.ToString());
249
}
250
else
251![]()
{
252
FileStream fs = new FileStream(_currentDir + @"\" + controlInfo.Parameter, FileMode.Create);
253
StreamWriter sw = new StreamWriter(fs);
254
sw.Write(sb.ToString());
255
sw.Close();
256
fs.Close();
257
DisplayLocalMessage("列表已保存为: " + controlInfo.Parameter + ".\r\n");
258
}
259
//if(
260
ReadReply(controlInfo);
261
Display(controlInfo.ReturnResult);
262
DisplayLocalMessage("列表完成: " + totalSize + " bytes, use time " +
263
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\r\n");
264![]()
265
return true;
266
}
267
catch (Exception e)
268![]()
{
269
DisplayLocalMessage(e.Message);
270
return false;
271
}
272
}
273![]()
274
private void DisplayCommand(string command)
275![]()
{
276
Console.ForegroundColor = ConsoleColor.Yellow;
277
Console.Write(command);
278
Console.ForegroundColor = ConsoleColor.White;
279
}
280![]()
281
private void DisplayLocalMessage(string message)
282![]()
{
283
Console.ForegroundColor = ConsoleColor.Red;
284
Console.Write(message);
285
Console.ForegroundColor = ConsoleColor.White;
286
}
287![]()
288
private IPEndPoint GetEndPoint(string strEndPoint)
289![]()
{
290
string[] endPoints = strEndPoint.Split(',');
291
string remoteIP = endPoints[0] + "." + endPoints[1] + "."
292
+ endPoints[2] + "." + endPoints[3];
293![]()
294
//endp[4] X 256 + endp[5];
295
int port = (Convert.ToInt32(endPoints[4]) * 256) + (int.Parse(endPoints[5]));
296
IPAddress ip = IPAddress.Parse(remoteIP);
297
IPEndPoint remoteEP = new IPEndPoint(ip, port);
298![]()
299
return remoteEP;
300
}
301![]()
302
private void Send(ControlInfo controlInfo)
303![]()
{
304
DisplayCommand(controlInfo.GetCommand());
305
NetworkStream ns = _commandControler.GetStream();
306
byte[] sendData = GetBytes(controlInfo.GetCommand());
307
ns.Write(sendData, 0, sendData.Length);
308
}
309![]()
310
private void Send(string command)
311![]()
{
312
DisplayCommand(command);
313
NetworkStream ns = _commandControler.GetStream();
314
byte[] sendData = GetBytes(command);
315
ns.Write(sendData, 0, sendData.Length);
316
}
317![]()
318
public void ExcuteCommand(string command)
319![]()
{
320
string cmd = "";
321
int index = 1;
322
bool isDone = false;
323
string paras = "";
324
for (; index <= command.Length && !isDone; index++)
325![]()
{
326
cmd = command.Substring(0, index);
327
paras = command.Substring(index);
328
isDone = DoCommand(cmd, paras);
329
}
330
if(!isDone)
331
DisplayCommand("Invalid command.\r\n");
332
}
333![]()
334
private bool DoCommand(string command, string parameter)
335![]()
{
336
switch (command.ToLower())
337![]()
{
338
case "get":
339
SetBinaryMode(true);
340
SetMode();
341
Excute("RETR" + parameter);
342
//FileInfo file = new FileInfo(parameter);
343
//File.
344
break;
345
case "put":
346
SetBinaryMode(true);
347
SetMode();
348
Excute("STOR" + parameter);
349
break;
350
case "dir":
351
Excute("PWD");
352
SetBinaryMode(false);
353
SetMode();
354
Excute("LIST" + parameter);
355
break;
356
case "pwd":
357
Excute("PWD");
358
break;
359
case "cd":
360
if (Excute("CWD" + parameter))
361![]()
{
362
DoCommand("dir", "");
363
}
364
break;
365
case "?":
366
GetHelp(parameter.Trim());
367
break;
368
case "quit":
369
Excute("QUIT");
370
break;
371
case "user":
372
return Login(parameter);
373
default:
374
return false;
375
}
376
return true;
377
}
378![]()
379
public bool Login(string usernameAndPassword)
380![]()
{
381
int index = usernameAndPassword.IndexOf(" ", 1);
382
_username = usernameAndPassword.Substring(0, index).Trim();
383
_password = usernameAndPassword.Substring(index + 1).Trim();
384
if (Excute("USER " + _username))
385![]()
{
386
if (Excute("PASS " + _password))
387![]()
{
388
return true;
389
}
390
}
391
return false;
392
}
393![]()
394
private void GetHelp(string para)
395![]()
{
396
string message = "Invalid command.";
397
switch (para)
398![]()
{
399
case "":
400
message="\t?\tget\tput\tdir\r\n\tcd\tquit";
401
break;
402
case "?":
403
message = "? 显示 ftp 命令说明.\r\n"
404
+ "格式: ? [command]\r\n"
405
+ "说明: [command]指定需要帮助的命令名称.如果没有指定 command,ftp 将显示全部命令的列表.";
406
break;
407
case "get":
408
message="get 使用当前文件转换类型将远程文件复制到本地计算机.\r\n"
409
+"格式: get remote-file [local-file]\r\n"
410
+"说明: remote-file 指定要复制的远程文件,\r\n"
411
+"local-file 指定要在本地计算机上使用的名称,若没指定,文件将命名为remote-file.";
412
break;
413
case "put":
414
message = "put 使用当前文件传送类型将本地文件复制到远程计算机上.\r\n"
415
+ "格式: put local-file [remote-file]\r\n"
416
+ "说明: local-file 指定要复制的本地文件,\r\n"
417
+ "remote-file 指定要在远程计算机上使用的名称,若没指定,文件将命名为local-file.";
418
break;
419
case "dir":
420
message = "dir 显示远程目录文件和子目录列表.\r\n"
421
+ "格式: dir [remote-directory] [local-file]\r\n"
422
+ "说明: remote-directory 指定要查看其列表的目录.如果没有指定目录,将使用远程计算机中的当前工作目录,\r\n"
423
+ "Local-file 指定要存储列表的本地文件.如果没有指定,输出将显示在屏幕上.";
424
break;
425
case "cd":
426
message = "cd 更改远程计算机上的工作目录.\r\n"
427
+ "格式: cd remote-directory\r\n"
428
+ "说明: remote-directory 指定要更改的远程计算机上的目录.";
429
break;
430
case "quit":
431
message = "quit 结束与远程计算机的 FTP 会话并退出 ftp.\r\n"
432
+ "格式: quit";
433
break;
434
case "user":
435
message = "user 指定远程计算机的用户.\r\n"
436
+ "格式: user username [password] [account]\r\n"
437
+ "说明: username 指定登录到远程计算机所使用的用户名.\r\n"
438
+ "password 指定 user-name 的密码.如果没有指定,但必须指定,ftp 会提示输入密码.";
439
break;
440
}
441
DisplayCommand(message + "\r\n");
442
}
443![]()
444
private bool SetMode()
445![]()
{
446
if (_isPassive)
447![]()
{
448
return Excute("PASV");
449
}
450
else
451![]()
{
452
return Excute("PORT");
453
}
454
}
455![]()
456
public bool Excute(string command)
457![]()
{
458
return Excute(ControlInfo.Create(command));
459
}
460![]()
461
public bool Excute(ControlInfo controlInfo)
462![]()
{
463
switch (controlInfo.Command)
464![]()
{
465
//用户
466
case "USER":
467
Send(controlInfo);
468
ReadReply(controlInfo);
469
Display(controlInfo.ReturnResult);
470
break;
471
//密码
472
case "PASS":
473
Send(controlInfo);
474
ReadReply(controlInfo);
475
Display(controlInfo.ReturnResult);
476
break;
477
//EPSV
478
case "EPSV":
479
Send(controlInfo);
480
ReadReply(controlInfo);
481
Display(controlInfo.ReturnResult);
482
break;
483
//被动模式
484
case "PASV":
485
Send(controlInfo);
486
ReadReply(controlInfo);
487
Display(controlInfo.ReturnResult);
488
if (controlInfo.Success)
489![]()
{
490
_isPassive = true;
491
SetTransferEndPoint(controlInfo.Message);
492
}
493
else
494
return false;
495
break;
496
//设定主动模式的数据连接端口
497
case "PORT":
498
return StartListener(controlInfo);
499
//文件及子目录列表
500
case "LIST":
501
return ReceiveList(controlInfo);
502
//下载文件
503
case "RETR":
504
return ReceiveData(controlInfo);
505
//名字系统类型
506
case "SYST":
507
Send(controlInfo);
508
ReadReply(controlInfo);
509
Display(controlInfo.ReturnResult);
510
break;
511
//上传文件
512
case "STOR":
513
return SendData(controlInfo);
514
//改变工作目录
515
case "CWD":
516
Send(controlInfo);
517
ReadReply(controlInfo);
518
Display(controlInfo.ReturnResult);
519
if (controlInfo.Success)
520![]()
{
521
SetServerDir(controlInfo.Message);
522
}
523
else
524![]()
{
525
return false;
526
}
527
break;
528
//当前目录
529
case "PWD":
530
Send(controlInfo);
531
ReadReply(controlInfo);
532
Display(controlInfo.ReturnResult);
533
break;
534
//传输模式
535
case "TYPE":
536
Send(controlInfo);
537
ReadReply(controlInfo);
538
Display(controlInfo.ReturnResult);
539
if (controlInfo.Success)
540![]()
{
541
switch (controlInfo.Parameter)
542![]()
{
543
case "I":
544
_isBinary = true;
545
break;
546
case "A":
547
_isBinary = false;
548
break;
549
}
550
}
551
break;
552
//退出
553
case "QUIT":
554
Send(controlInfo);
555
ReadReply(controlInfo);
556
Display(controlInfo.ReturnResult);
557
Close();
558
break;
559
default:
560
Display("This is '" + controlInfo.Command + "' not implemented.\n");
561
return false;
562
}
563
return true;
564
}
565![]()
566
private void SetServerDir(string dir)
567![]()
{
568
int startIndex = dir.IndexOf("to ") + 3;
569
int length = dir.LastIndexOf("\r\n") - startIndex;
570
_serverDir = dir.Substring(startIndex, length);
571
}
572![]()
573
private bool SendData(ControlInfo controlInfo)
574![]()
{
575
if (controlInfo.Parameter2.Length > 0)
576![]()
{
577
Send(controlInfo.Command + " " + controlInfo.Parameter2 + "\r\n");
578
}
579
else
580![]()
{
581
Send(controlInfo);
582
}
583
ReadReply(controlInfo);
584
Display(controlInfo.ReturnResult);
585![]()
586
if (!controlInfo.Success)
587![]()
{
588
Display("传送失败!\r\n");
589
return false;
590
}
591
InitDataControler();
592![]()
593
try
594![]()
{
595
int startTime = Environment.TickCount;
596![]()
597
string file = _currentDir + @"\" + controlInfo.Parameter;
598
FileInfo fileInfo = new FileInfo(file);
599
if (!fileInfo.Exists)
600![]()
{
601
Display(fileInfo.FullName + " : No such file.\r\n");
602
_dataControler.Close();
603
return false;
604
}
605
if (_isBinary)
606![]()
{
607
_dataControler.Client.SendFile(file);
608
609
}
610
else
611![]()
{
612
FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);
613
StreamReader sr = new StreamReader(fs);
614
byte[] buffer = GetBytes(sr.ReadToEnd());
615
_dataControler.GetStream().Write(buffer, 0, buffer.Length);
616
sr.Close();
617
fs.Close();
618
}
619
_dataControler.Close();
620![]()
621
controlInfo.SuccessCode = 226;
622
ReadReply(controlInfo);
623
Display(controlInfo.ReturnResult);
624
double useTime = GetUseTime(startTime, Environment.TickCount);
625
double speed = fileInfo.Length / useTime;
626![]()
627
if (controlInfo.Success)
628![]()
{
629
Display("已传送 " + controlInfo.Parameter + " " + fileInfo.Length + " bytes, use time " +
630
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\n");
631
//Display("已传数: " + controlInfo.Parameter + " " + fileInfo.Length + " bytes.\n");
632
}
633
else
634![]()
{
635
Display(controlInfo.Parameter + " 传送失败!\r\n");
636
}
637
return true;
638
}
639
catch (Exception e)
640![]()
{
641
DisplayLocalMessage(e.Message);
642
return false;
643
}
644
}
645![]()
646
private void SetTransferEndPoint(string endPoint)
647![]()
{
648
int offset = endPoint.IndexOf("(") + 1;
649
int length = endPoint.LastIndexOf(")") - offset;
650
endPoint = endPoint.Substring(offset, length);
651
_transferEndPoint = GetEndPoint(endPoint);
652
}
653![]()
654![]()
/**//// <summary>
655
/// 计算传输时间,以秒为单位
656
/// </summary>
657
/// <param name="startTime">开始的毫秒数</param>
658
/// <param name="endTime">结束的毫秒数</param>
659
/// <returns></returns>
660
private double GetUseTime(int startTime, int endTime)
661![]()
{
662
double useTime = ((double)(endTime - startTime)) / 1000;
663
if (useTime == 0)
664![]()
{
665
useTime = 0.01;
666
}
667
return useTime;
668
}
669![]()
670
private string GetSpeed(double speed)
671![]()
{
672
string unit = " Bytes/S";
673
if (speed > 1000)
674![]()
{
675
speed = speed / 1000;
676
unit = " KB/S";
677
}
678
if (speed > 1000)
679![]()
{
680
speed = speed / 1000;
681
unit = " MB/S";
682
}
683
if (speed > 1000)
684![]()
{
685
speed /= 1000;
686
unit = " GB/S";
687
}
688
return speed.ToString("f2") + unit;
689
}
690![]()
691
private bool StartListener(ControlInfo controlInfo)
692![]()
{
693
int p = controlInfo.Parameter.Length > 0 ? Convert.ToInt32(controlInfo.Parameter) : 0;
694
IPEndPoint localEP = new IPEndPoint(_clientIP, p);
695
_listener = new TcpListener(localEP);
696
_listener.Start();
697
DisplayLocalMessage("已打开数据监听连接 IP:" + _listener.LocalEndpoint.ToString() + "\r\n");
698
//CultureInfo ci = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();
699
//NumberFormatInfo nfi = ci.NumberFormat;
700![]()
/**/////Set our format to "123,456"
701
//nfi.CurrencyPositivePattern = 1;
702
//nfi.CurrencyGroupSeparator = ",";
703
//nfi.CurrencySymbol = "";
704
//nfi.CurrencyDecimalDigits = 0;
705
//ci.NumberFormat = nfi;
706![]()
707
//Thread.CurrentThread.CurrentCulture = ci;
708
localEP = (IPEndPoint)_listener.LocalEndpoint;
709![]()
710
string ip = localEP.Address.ToString().Replace(".", ",");
711
//string port = localEP.Port.ToString("C");
712
int p1 = localEP.Port / 256;
713
int p2 = localEP.Port % 256;
714
controlInfo.Parameter = ip + "," + p1 + "," + p2;
715![]()
716
Send(controlInfo);
717
ReadReply(controlInfo);
718
Display(controlInfo.ReturnResult);
719
if (controlInfo.Success)
720![]()
{
721
_isPassive = false;
722
}
723
else
724
return false;
725
return true;
726
}
727![]()
728
private void Display(string str)
729![]()
{
730
Console.ForegroundColor = ConsoleColor.Green;
731
Console.Write(str);
732
Console.ForegroundColor = ConsoleColor.White;
733
}
734![]()
735![]()
/**//// <summary>
736
/// 将字符串转换成UTF8码的字节数组,这样可以传输中文等
737
/// </summary>
738
/// <param name="response"></param>
739
/// <returns></returns>
740
private byte[] GetBytes(string response)
741![]()
{
742
return GetBytes(response, Encoding.Default);
743
}
744![]()
745
private byte[] GetBytes(string response, Encoding encoder)
746![]()
{
747
return encoder.GetBytes(response.ToCharArray());
748
}
749![]()
750
//private void Append(StringBuilder sb, byte[] data)
751
//{
752
// sb.Append(Encoding.Default.GetString(data));
753
//}
754![]()
755
private string GetString(byte[] datas)
756![]()
{
757
return GetString(datas, 0, datas.Length);
758
}
759![]()
760
private string GetString(byte[] datas, int offset, int size)
761![]()
{
762
return GetString(datas, offset, size, Encoding.Default);
763
}
764![]()
765
private string GetString(byte[] datas, int offset, int size, Encoding encoder)
766![]()
{
767
return encoder.GetString(datas, offset, size);
768
}
769
}
770
}
771
代码未经整理,呵呵,等寒假再回来重构一下.
1. get remote-file [local-file] :从Server下载的一个文件
2. put local-file [remote-file] :传给Server一个文件
3. pwd :显示Server当前目录
4. dir :列出Server当前目录
5. cd directory :改变Server当前目录
6. ? [command] :显示所提供的命令
7. quit :退出返回
1
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.IO;5
using System.Net;6
using System.Net.Sockets;7
using System.Threading;8

9
namespace FtpServer10


{11
public class MainApp12

{13
public static string FtpRoot = @"E:\FTP";14

15
public static void getHelp()16

{17
Console.WriteLine("Ftp help:");18
Console.WriteLine("-r [path]\t:\tChange FTP Root");19
Console.WriteLine("-? \t:\tGet Help");20
}21

22
public static void Main(string[] args)23

{24
for (int i = 0; i < args.Length; i++)25

{26
switch (args[i])27

{ 28
case "-r":29
FtpRoot = args[i + 1];30
break;31
case "-?":32
getHelp();33
break;34
default:35
36
FtpRoot = Directory.GetCurrentDirectory();37
break;38
}39
}40
Console.WriteLine("FTP server Start");41
//创建一个FTP对象42
Ftp ftp = new Ftp();43
//启动Ftp44
if (ftp.Start() == false)45

{46
Console.WriteLine("Failed to start FTP Server.");47
}48
}49
}50
}51

1
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.IO;5
using System.Net;6
using System.Net.Sockets;7
using System.Threading;8

9
namespace FtpServer10


{11
public class SessionInfo12

{13
private bool _binary;14

15
public bool Binary16

{17

get
{ return _binary; }18

set
{ _binary = value; }19
}20
private bool _passive;21

22
public bool Passive23

{24

get
{ return _passive; }25

set
{ _passive = value; }26
}27
private string _ftpRoot;28

29
public string FtpRoot30

{31

get
{ return _ftpRoot; }32

set
{ _ftpRoot = value; }33
}34
private string _userName;35

36
public string UserName37

{38

get
{ return _userName; }39

set
{ _userName = value; }40
}41
private PassiveInfo _passiveInfo;42

43
public PassiveInfo PassiveInfo44

{45

get
{ return _passiveInfo; }46

set
{ _passiveInfo = value; }47
}48

49
private IPEndPoint _remoteEP;50

51
public IPEndPoint RemoteEP52

{53

get
{ return _remoteEP; }54

set
{ _remoteEP = value; }55
}56

57
private string _username = "";58

59
public string Username60

{61

get
{ return _username; }62

set
{ _username = value; }63
}64
private string _password = "";65

66
public string Password67

{68

get
{ return _password; }69

set
{ _password = value; }70
}71
72
public SessionInfo()73

{74
_binary = true;75
_passive = true;76
_ftpRoot = MainApp.FtpRoot;77
_userName = "";78
_passiveInfo = new PassiveInfo();79
_remoteEP = null;80
}81
}82

83
public class PassiveInfo84

{85
private IPHostEntry _IPHostEntry;86

87
public IPHostEntry IPHostEntry88

{89

get
{ return _IPHostEntry; }90

set
{ _IPHostEntry = value; }91
}92
private TcpListener _tcpListener;93

94
public TcpListener TcpListener95

{96

get
{ return _tcpListener; }97

set
{ _tcpListener = value; }98
}99
private IPEndPoint _remoteEP;100

101
public IPEndPoint RemoteEP102

{103

get
{ return _remoteEP; }104

set
{ _remoteEP = value; }105
}106

107
public PassiveInfo()108

{109
_IPHostEntry = null;110
_tcpListener = null;111
_remoteEP = null;112
}113

114
public PassiveInfo(IPHostEntry host, TcpListener listener, IPEndPoint remoteEP)115

{116
_IPHostEntry = host;117
_tcpListener = listener;118
_remoteEP = remoteEP;119
}120
}121
}122

1
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.IO;5
using System.Net;6
using System.Net.Sockets;7
using System.Threading;8
using System.Globalization;9

10
namespace FtpServer11


{12
public class Ftp13

{14
private TcpListener _tcpListener;15
private Socket _socket;16
private IPHostEntry _IPHostEntry;17
private IPEndPoint _IPEndPoint;18

19
public Ftp()20

{21
_IPHostEntry = Dns.GetHostEntry(Dns.GetHostName());22
_IPEndPoint = new IPEndPoint(_IPHostEntry.AddressList[0], 21);23
_tcpListener = new TcpListener(_IPEndPoint);24
}25

26
public bool Start()27

{28
try29

{30
_tcpListener.Start();31
while (true)32

{33
//接收到客户端的一个连接请求,返回一个Socket响应它,采用多线程方式,支持多用户同时访问34
//此Socket是处理用户的控制连接35
_socket = _tcpListener.AcceptSocket();36
Thread client = new Thread(new ThreadStart(ServerConnection));37
client.Start();38
}39
}40
catch (SocketException se)41

{42
Console.WriteLine("Error: {0}", se.Message);43
return false;44
}45
}46

47
public void Reply(Socket socket, int responseCode, string message)48

{49
try50

{51
string response = responseCode + " " + message + "\r\n";52
byte[] datas = GetBytes(response);53
socket.Send(datas);54
}55
catch (Exception e)56

{57
Console.WriteLine(e.Message);58
}59
}60

61
private byte[] GetBytes(string response)62

{63
return GetBytes(response, Encoding.Default);64
}65

66
private byte[] GetBytes(string response, Encoding encoder)67

{68
return encoder.GetBytes(response);69
}70

71
private string GetString(byte[] datas, int offset, int size)72

{73
return GetString(datas, offset, size, Encoding.Default);74
}75

76
private string GetString(byte[] datas, int offset, int size, Encoding encoder)77

{78
return encoder.GetString(datas, offset, size);79
}80

81

/**//// <summary>82
/// 处理一个连接请求83
/// </summary>84
private void ServerConnection()85

{86
//这里需要互斥访问??87
Socket socket = _socket;88
//建立一个新会话89
SessionInfo session = new SessionInfo();90
session.RemoteEP = (IPEndPoint)socket.RemoteEndPoint;91
//显示服务器信息92
string message = "Welcome to MK FTP Server v1.0, Base on .NET Framework 2.0.";93
Reply(socket, 220, message);94

95
//分析用户命令96
CheckCommand(socket, session);97
}98

99
private void CheckCommand(Socket socket, SessionInfo session)100

{101
try 102

{103
//循环执行用户命令104
while (true)105

{106
byte[] buffer = new byte[256];107
//接收命令108
int dataSize = socket.Receive(buffer);109
string cmd = GetString(buffer, 0, dataSize).Replace("\r\n", "");110
string command = "";111
string parameter = "";112
if (cmd.Length == 3)113
command = cmd;114
else115
command = cmd.Substring(0, 3);116
string paras = "";117
command = command.ToUpper();118
if (command != "CWD" && command != "PWD")119

{120
command = cmd.Substring(0, 4).ToUpper();121
if (cmd.Length > 4)122
parameter = cmd.Substring(5);123
}124
else125

{126
if (cmd.Length > 3)127

{128
parameter = cmd.Substring(4);129
}130
}131
//for (int i = 0; i < 4; i++)132
//{ 133
// //不是回车换行符134
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)135
// {136
// command += (char)buffer[i];137
// }138
//}139
//if (command != "CWD" && command != "PWD")140
//{141
// for (int i = 5; i < buffer.Length; i++)142
// {143
// //不是回车换行符144
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)145
// {146
// parameter += (char)buffer[i];147
// }148
// }149
//}150
//else151
//{152
// for (int i = 4; i < buffer.Length; i++)153
// {154
// //不是回车换行符155
// if (buffer[i] != 0 && buffer[i] != 13 && buffer[i] != 10 && buffer[i] != 32)156
// {157
// parameter += (char)buffer[i];158
// }159
// }160
//}161
//parameter = parameter.Trim();162
System.Console.WriteLine("From {0} : {1} {2}", socket.RemoteEndPoint, command, parameter);163

164
//FTP命令格式:前4位为命令类型,后面为命令参数165
switch (command)166

{ 167
//用户168
case "USER":169
session.UserName = parameter;170
Reply(socket, 331, "User name okey, need password.");171
break;172
//密码173
case "PASS":174
session.Password = parameter;175
AuthenticateUser(socket, session.UserName, session.Password);176
break;177
//EPSV 扩展被动模式178
case "EPSV":179
Reply(socket, 522, "Extended Passive Mode not supported.");180
break;181
//被动模式182
case "PASV":183
session.Passive = true;184
ProcessPassiveCommand(socket, parameter, session);185
break;186
//设定主动模式的数据连接端口187
case "PORT":188
session.Passive = false;189
ProcessPortCommand(socket, parameter, session);190
break;191
//文件及子目录列表192
case "LIST":193
ProcessListCommand(socket, parameter, session);194
break;195
//发送客户端下载的文件196
case "RETR":197
ProcessRetreiveCommand(socket, parameter, session);198
break;199
//名字系统类型200
case "SYST":201
Reply(socket, 215, System.Environment.OSVersion.VersionString);202
break;203
//上传文件204
case "STOR":205
ProcessStoreCommand(socket, parameter, session);206
break;207
//改变工作目录208
case "CWD":209
ProcessCWDCommand(socket, parameter, session);210
break;211
//当前目录212
case "PWD":213
ProcessPWDCommand(socket, parameter, session);214
break;215
//传输模式216
case "TYPE":217
switch (parameter)218

{ 219
case "I":220
session.Binary = true;221
Reply(socket, 200, "Type set to I.");222
break;223
case "A":224
session.Binary = false;225
Reply(socket, 200, "Type set to A.");226
break;227
default:228
Reply(socket, 200, "Type not change.");229
break;230
}231
break;232
//退出233
case "QUIT":234
Reply(socket, 221, "Goodbye!.");235
socket.Close();236
return;237
default:238
Reply(socket, 502, "'" + command + "': not implemented.");239
break;240
}241
}242
}243
catch (Exception e)244

{245
Console.WriteLine(e.Message);246
}247
}248

249
private void ProcessPWDCommand(Socket socket, string parameter, SessionInfo session)250

{251
Reply(socket, 257, "\"" + session.FtpRoot + "\" is current directory.");252
}253

254
private void ProcessCWDCommand(Socket socket, string parameter, SessionInfo session)255

{256
if (parameter.IndexOf("\\") > 0 && parameter.IndexOf(":") > 0)257

{258
session.FtpRoot = parameter;259
}260
else261

{262
session.FtpRoot += @"\" + parameter;263
}264
265
DirectoryInfo dir = new DirectoryInfo(session.FtpRoot);266
if (!dir.Exists)267

{268
Reply(socket, 550, dir.FullName + ": No such directory.");269
return;270
}271
Reply(socket, 250, "Directory changed to "+dir.FullName);272
}273

274
private void ProcessStoreCommand(Socket socket, string parameter, SessionInfo session)275

{276
try277

{278
string file = session.FtpRoot + @"\" + parameter;279
FileStream fs = new FileStream(file, FileMode.Create);280

281
byte[] buffer = new byte[1024];282

283
int dataSize = 0;284

285
if (session.Binary)286

{287
Reply(socket, 150, "Opening BINARY mode data connection for " + parameter);288
BinaryWriter bw = new BinaryWriter(fs);289
Socket binarySocket;290
if (session.Passive)291

{292
binarySocket = session.PassiveInfo.TcpListener.AcceptSocket();293

294
}295
else296

{297
binarySocket = new Socket(AddressFamily.InterNetwork,298
SocketType.Stream, ProtocolType.Tcp);299
binarySocket.Bind(new IPEndPoint(_IPEndPoint.Address, 0));300
binarySocket.Connect(session.RemoteEP);301
}302
while ((dataSize = binarySocket.Receive(buffer)) > 0)303

{304
bw.Write(buffer, 0, dataSize);305
}306
bw.Close();307
binarySocket.Close();308
}309
else310

{311
//FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);312
//Reply(socket, 150, "Opening ASCII mode data connection for " + parameter313
// + " (" + fileInfo.Length + " Bytes).");314
//StreamReader sr = new StreamReader(fs);315
//if (session.Passive)316
//{317
// SendOverPassiveDataConnection(GetBytes(sr.ReadToEnd(), Encoding.UTF8), session);318

319
//}320
//else321
//{322
// SendOverDataConnection(GetBytes(sr.ReadToEnd(), Encoding.UTF8), session);323
//}324
//sr.Close();325
//fs.Close();326
}327

328
Reply(socket, 226, "Transfer Complete");329

330
}331
catch (Exception e)332

{333
Console.WriteLine(e.Message);334
}335
}336

337
private void ProcessRetreiveCommand(Socket socket, string parameter, SessionInfo session)338

{339
try340

{341
string file = session.FtpRoot + @"\" + parameter;342
FileInfo fileInfo =new FileInfo(file);343
if (!fileInfo.Exists)344

{345
Reply(socket, 550, fileInfo.FullName + ": No such file.");346
return;347
}348
if (session.Binary)349

{350
Reply(socket, 150, "Opening BINARY mode data connection for " + parameter351
+ " (" + fileInfo.Length + " Bytes)");352
//BinaryReader br = new BinaryReader(fs);353
Socket binarySocket;354
if (session.Passive)355

{356
binarySocket = session.PassiveInfo.TcpListener.AcceptSocket();357
}358
else359

{360
binarySocket = new Socket(AddressFamily.InterNetwork,361
SocketType.Stream, ProtocolType.Tcp);362
binarySocket.Bind(new IPEndPoint(_IPEndPoint.Address, 0));363
binarySocket.Connect(session.RemoteEP);364
}365
//while (br.PeekChar() > -1)366
//{367
// binarySocket.Send(br.ReadBytes(10240));368
// //binarySocket.369
//}370
//br.Close();371
binarySocket.SendFile(fileInfo.FullName);372
binarySocket.Close();373
}374
else375

{376
FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);377
Reply(socket, 150, "Opening ASCII mode data connection for " + parameter378
+ " (" + fileInfo.Length + " Bytes).");379
StreamReader sr = new StreamReader(fs);380
if (session.Passive)381

{382
SendOverPassiveDataConnection(GetBytes(sr.ReadToEnd()), session);383

384
}385
else386

{387
SendOverDataConnection(GetBytes(sr.ReadToEnd()), session);388
}389
sr.Close();390
fs.Close();391
}392
393
Reply(socket, 200, "Transfer Complete");394
395
}396
catch (Exception e)397

{398
Console.WriteLine(e.Message);399
}400
}401

402
private void ProcessListCommand(Socket socket, string parameter, SessionInfo session)403

{404
DirectoryInfo curDir = new DirectoryInfo(session.FtpRoot);405
DirectoryInfo[] dirInfoList = curDir.GetDirectories();406
FileInfo[] fileSysInfoList = curDir.GetFiles();407

408
const string s_dir = "\t";//"┼ <DIR> ";409
const string s_file = "";// "├ ";410
const string s_d_right = "drw-rw-rw-";411
const string s_f_right = "_rw-rw-rw-";412
const string s_1 = " ";413
const string s_3 = " ";414
const string s_7 = " ";415
const string s_10 = " ";416
StringBuilder sb = new StringBuilder();417
foreach (DirectoryInfo dir in dirInfoList)418

{419
//sb.Append(s_d_right + s_1 + "1 user" + s_1 + "group" + s_1 + 0 + s_1 + dir.LastWriteTime + s_1 + dir.Name);420
//sb.Append("\r\n");421
GetFormatRow(sb, s_d_right, 0, dir.LastWriteTime, dir.Name);422
}423

424
foreach (FileInfo file in fileSysInfoList)425

{426
//sb.Append(s_f_right + s_1 + "1 user" + s_1 + "group" + s_1 + file.Length + s_1 + file.LastWriteTime + s_1 + file.Name);427
//sb.Append("\r\n");428
GetFormatRow(sb, s_f_right, file.Length, file.LastWriteTime, file.Name);429
}430

431
Reply(socket, 150, "Opening ASCII mode data connection for /bin/ls.");432
if (session.Passive)433

{434
SendOverPassiveDataConnection(GetBytes(sb.ToString()), session);435
}436
else437

{438
SendOverDataConnection(GetBytes(sb.ToString()), session);439
}440
Console.WriteLine("Listed.");441
//socket.442
Reply(socket, 226, "Transfer complete.");443

444
}445

446
private string GetFormatRow(StringBuilder sb, string right, Int64 size, DateTime date, string name)447

{448
const string s_1 = " ";449
sb.Append(right + s_1);450
sb.Append("user group ");451
for (int i = size.ToString().Length; i < 12; i++)452

{453
sb.Append(s_1);454
}455
sb.Append(size + s_1);456
sb.Append(date.ToString("MMM d hh:ss ", DateTimeFormatInfo.InvariantInfo));457
sb.Append(name + "\r\n");458
return sb.ToString();459
}460

461

/**//// <summary>462
/// 主动模式下传输数据463
/// </summary>464
/// <param name="p"></param>465
private bool SendOverDataConnection(byte[] datas, SessionInfo session)466

{467
try468

{469
Console.WriteLine("Connecting Client: {0}
", session.RemoteEP);470
TcpClient tcpClient = new TcpClient();471
tcpClient.Connect(session.RemoteEP);472
//Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);473
//IPEndPoint localEP = new IPEndPoint(_IPEndPoint.Address, 0);474
//s.Bind(localEP);475
//s.Connect(session.RemoteEP);476
//s.Send(datas);477

478
Console.WriteLine("Connected, Sending data
");479
NetworkStream ns = tcpClient.GetStream();480
ns.Write(datas, 0, datas.Length);481
Console.WriteLine("Sended.");482
//s.Close();483
ns.Close();484
tcpClient.Close();485
}486
catch (SocketException se)487

{488
Console.WriteLine(se.Message);489
return false;490
}491
return true;492
}493

494
private bool SendOverPassiveDataConnection(byte[] datas, SessionInfo session)495

{496
try497

{498
Console.WriteLine("Connecting Client: {0}
", session.RemoteEP);499
TcpClient tcpClient = session.PassiveInfo.TcpListener.AcceptTcpClient();500

501
Console.WriteLine("Connected, Sending data
");502
NetworkStream ns = tcpClient.GetStream();503
ns.Write(datas, 0, datas.Length);504
//int d=ns.DataAvailable505
Thread.Sleep(100); //防止发送太快,客户端接收错误506
Console.WriteLine("Sended.");507
//s.Close();508
ns.Close();509
tcpClient.Close();510
}511
catch (SocketException se)512

{513
Console.WriteLine(se.Message);514
return false;515
}516
return true;517
}518

519

/**//// <summary>520
/// 用户指定端口,用于主动传输模式。每次传输前,用户都会设置端口521
/// </summary>522
/// <param name="socket"></param>523
/// <param name="parameter"></param>524
private void ProcessPortCommand(Socket socket, string parameter, SessionInfo session)525

{526
string[] endPoints = parameter.Split(',');527
string remoteIP = endPoints[0] + "." + endPoints[1] + "." 528
+ endPoints[2] + "." + endPoints[3];529
//int port = Convert.ToInt32(endPoints[4] + endPoints[5]);530
//endp[4] X 256 + endp[5];531
int port = (Convert.ToInt32(endPoints[4]) * 256) + (int.Parse(endPoints[5]));532
IPAddress ip = IPAddress.Parse(remoteIP);533
IPEndPoint remoteEP = new IPEndPoint(ip, port);534

535
session.RemoteEP = remoteEP;536
Reply(socket, 200, "PORT Command successful.");537
Console.WriteLine("PORT SET");538
}539

540
//响应被动模式命令541
private void ProcessPassiveCommand(Socket socket, string parameter, SessionInfo session)542

{543
//创建一个空闲EP544
IPEndPoint hostEP = new IPEndPoint(_IPHostEntry.AddressList[0], 0);545
TcpListener tcpListener = new TcpListener(hostEP);546
session.PassiveInfo.IPHostEntry = _IPHostEntry;547
session.PassiveInfo.TcpListener = tcpListener;548
//session.PassiveInfo.RemoteEP = hostEP;549
session.Passive = true;550
session.PassiveInfo.TcpListener.Start();551

552
IPEndPoint localEP = (IPEndPoint)tcpListener.LocalEndpoint;553
string ip = localEP.Address.ToString().Replace(".", ",");554
int p1 = localEP.Port / 256;555
int p2 = localEP.Port % 256;556

557
Reply(socket, 227, "Entering Passive Mode (" + ip + "," + p1 + "," + p2 + ")");558

559
}560

561
private void AuthenticateUser(Socket socket, string username, string password)562

{563
//do Authenticate user name and password564
Reply(socket, 230, "User logged in, proceed.");565
}566
}567

568
569
}570

1
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.IO;5
using System.Net;6
using System.Net.Sockets;7
using System.Threading;8
using System.Globalization;9

10
namespace FtpClient11


{12
class ClientMainApp13

{14
static void Main(string[] args)15

{16
try17

{18
IPHostEntry server;19
try20

{21
server = Dns.GetHostEntry(IPAddress.Parse(args[0]));22
}23
catch24

{25
server = Dns.GetHostEntry(args[0]);26
}27

28
29

30
IPEndPoint serverEP = new IPEndPoint(server.AddressList[0], 21);31

32
FtpViewer browser = new FtpViewer(serverEP);33
browser.Start();34

35

/**/////登录FTP Server36
//Console.WriteLine("USER anonymous");37
//browser.Excute("USER anonymous");38
//Console.WriteLine("PASS 1111");39
//browser.Excute("PASS 1111");40
//Console.WriteLine("SYST");41
//browser.Excute("SYST");42
//Console.WriteLine("PWD");43
//browser.Excute("PWD");44
//Console.WriteLine("TYPE A");45
//browser.Excute("TYPE A");46
//Console.WriteLine("PORT");47
//browser.Excute("PORT");48
//Console.WriteLine("LIST");49
//browser.Excute("LIST");50
//browser.ExcuteCommand("dir");51

52

53

54

/**///////下载文件55
////Console.WriteLine("TYPE I");56
////browser.Excute("TYPE I");57
////Console.WriteLine("PASV");58
////browser.Excute("PASV");59
////Console.WriteLine("RETR picture.JPG");60
////browser.Excute("RETR picture.JPG");61
//browser.ExcuteCommand("get picture.JPG");62

63

/**///////更改目录64
////Console.WriteLine("CWD files");65
////browser.Excute("CWD files");66
////Console.WriteLine("PWD");67
////browser.Excute("PWD");68
////Console.WriteLine("PASV");69
////browser.Excute("PASV");70
////Console.WriteLine("LIST -al");71
////browser.Excute("LIST -al");72
//browser.ExcuteCommand("cd files");73

74

/**///////上传文件75
////Console.WriteLine("TYPE I");76
////browser.Excute("TYPE I");77
////Console.WriteLine("PASV");78
////browser.Excute("PASV");79
////Console.WriteLine("STOR network4.rar");80
////browser.Excute("STOR network4.rar");81
//browser.ExcuteCommand("put network4.rar");82

83

/**/////Console.WriteLine("RETR testFiles222.txt");84
////browser.Excute("RETR testFiles222.txt");85
////Console.WriteLine("RETR testFiles1.txt");86
////browser.Excute("RETR testFiles1.txt");87
////Console.WriteLine("RETR picture.JPG");88
////browser.Excute("RETR picture.JPG");89
////Console.WriteLine("RETR network4.rar");90
////browser.Excute("RETR network4.rar");91
////Console.WriteLine("R2TR sdlfjldjgsd");92
////browser.Excute("R2TR sdlfjldjgsd");93
////Console.WriteLine("CWD files");94
////browser.Excute("CWD files");95
////Console.WriteLine("RETR files_ftp应答码.txt");96
////browser.Excute("RETR files_ftp应答码.txt");97

98
////browser.ExcuteCommand("quit");99
//browser.ExcuteCommand("user anonymous 123");100
while (browser.IsRunning)101

{102
Console.Write("ftp> ");103
string cmd = Console.ReadLine();104
browser.ExcuteCommand(cmd);105
}106
}107
catch (Exception e)108

{109
Console.WriteLine(e.Message);110
}111
//Console.Read();112
}113

114
115
}116
}117

1
using System;2
using System.Collections.Generic;3
using System.Text;4

5
namespace FtpClient6


{7
public class ControlInfo8

{9
private string _sendCommand;10

11
public string SendCommand12

{13

get
{ return _sendCommand; }14

set
{ _sendCommand = value; }15
}16

17
private string _command;18

19
public string Command20

{21

get
{ return _command; }22

set
{ _command = value; }23
}24
private string _parameter;25

26
public string Parameter27

{28

get
{ return _parameter; }29

set
{ _parameter = value; }30
}31

32
private string _parameter2 = "";33

34
public string Parameter235

{36

get
{ return _parameter2; }37

set
{ _parameter2 = value; }38
}39

40
private int _successCode;41

42
public int SuccessCode43

{44

get
{ return _successCode; }45

set
{ _successCode = value; }46
}47
private int _returnCode;48

49
public int ReturnCode50

{51

get
{ return _returnCode; }52

set
{ _returnCode = value; }53
}54
private string _message;55

56
public string Message57

{58

get
{ return _message; }59

set
{ _message = value; }60
}61

62
private string _returnResult;63

64
public string ReturnResult65

{66

get
{ return _returnResult; }67

set
{ _returnResult = value; }68
}69

70
public ControlInfo()71

{72
_successCode = 220;73
}74

75
public ControlInfo(string cmd, string paras)76

{77
_command = cmd;78
_parameter = paras;79
_successCode = GetSuccessCode(cmd);80
}81

82
public ControlInfo(string sendCommand, string cmd, string paras)83

{84
_sendCommand = sendCommand;85
_command = cmd;86
_parameter = paras;87
_successCode = GetSuccessCode(cmd);88
}89

90
public ControlInfo(string sendCommand, string cmd, string paras, string paras2)91

{92
_sendCommand = sendCommand;93
_command = cmd;94
_parameter = paras;95
_parameter2 = paras2;96
_successCode = GetSuccessCode(cmd);97
}98

99
//指示此初操作命令是否成功100
public bool Success101

{102
get103

{104
return _returnCode == _successCode;105
}106
}107

108

/**//// <summary>109
/// 获取带参数的命令110
/// </summary>111
/// <returns></returns>112
public string GetCommand()113

{114
return _command + (_parameter.Length > 0 ? " " + _parameter : "") + "\r\n";115
}116

117

/**//// <summary>118
/// 获取指定命令成功执行希望得到响应的代码119
/// </summary>120
/// <param name="command"></param>121
/// <returns></returns>122
public static int GetSuccessCode(string command)123

{124
switch (command)125

{126
//用户127
case "USER":128
return 331;129
//密码130
case "PASS":131
return 230;132
//EPSV133
case "EPSV":134
return 522;135
//被动模式136
case "PASV":137
return 227;138
//设定主动模式的数据连接端口139
case "PORT":140
return 200;141
//文件及子目录列表142
case "LIST":143
return 150;144
//发送客户端下载的文件145
case "RETR":146
return 150;147
//名字系统类型148
case "SYST":149
return 215;150
//上传文件151
case "STOR":152
return 150;153
//改变工作目录154
case "CWD":155
return 250;156
//当前目录157
case "PWD":158
return 257;159
//传输模式160
case "TYPE":161
return 200;162
default:163
return 0;164
}165
}166

167
public static ControlInfo Create(string command)168

{169
string cmd = "";170
if (command.Length == 3)171
cmd = command;172
else173
cmd = command.Substring(0, 3);174
string paras = "";175
cmd = cmd.ToUpper();176
if (cmd != "CWD" && cmd != "PWD")177

{178
cmd = command.Substring(0, 4).ToUpper();179
if (command.Length > 4)180
paras = command.Substring(5);181
}182
else183

{184
if (command.Length > 3)185

{186
paras = command.Substring(4);187
}188
}189
if (paras.IndexOf(" ") > 0)190

{191
int index = paras.IndexOf(" ");192
string paras2 = paras.Substring(index + 1);193
paras = paras.Substring(0, index);194
ControlInfo cInfo2 = new ControlInfo(command, cmd, paras, paras2);195
return cInfo2;196
}197
ControlInfo cInfo = new ControlInfo(command, cmd, paras);198
return cInfo;199
}200
}201
}202

1
using System;2
using System.Collections.Generic;3
using System.Text;4
using System.IO;5
using System.Net;6
using System.Net.Sockets;7
using System.Threading;8
using System.Globalization;9
using System.Collections;10

11
namespace FtpClient12


{13
public class FtpViewer14

{15
private TcpClient _commandControler;16
private TcpListener _listener;17
private TcpClient _dataControler;18
private IPEndPoint _serverEndPoint;19
private IPEndPoint _transferEndPoint;20
private IPAddress _clientIP;21
private string _username;22
private string _password;23
private string _currentDir;24
private string _serverDir = @"\";25
private bool _isPassive = true; //默认被动模式,采用二进制模式传输数据26
private bool _isBinary = true;27
private bool _isRunning = false;28

29
public bool IsRunning30

{31

get
{ return _isRunning; }32

set
{ _isRunning = value; }33
}34

35
public FtpViewer()36

{ 37
38
}39

40
public FtpViewer(IPEndPoint serverEndPoint)41

{42
_clientIP = Dns.GetHostEntry(Dns.GetHostName()).AddressList[0];43
_serverEndPoint = serverEndPoint;44
_commandControler = new TcpClient();45
_currentDir = System.Environment.CurrentDirectory;46
}47

48
public void SetBinaryMode(bool isBinary)49

{50
if (isBinary != _isBinary)51

{52
_isBinary = isBinary;53
if (isBinary)54

{55
Excute("TYPE I");56
}57
else58

{59
Excute("TYPE A");60
}61
}62
}63

64
public bool Start()65

{66
_commandControler.Connect(_serverEndPoint);67
ControlInfo controlInfo = new ControlInfo();68
ReadReply(controlInfo);69
Display(controlInfo.ReturnResult);70

71
DisplayCommand("User (" + _serverEndPoint.ToString() + ":) ");72
Login(Console.ReadLine());73

74
_isRunning = true;75
return true;76
}77

78
public void Close()79

{80
if (_commandControler != null)81

{82
_commandControler.Close();83
_commandControler = null;84
}85
if (_dataControler != null)86

{87
_dataControler.Close();88
_dataControler = null;89
}90
_isRunning = false;91
}92

93
public bool ReadReply(ControlInfo controlInfo)94

{95
try96

{97
NetworkStream ns = _commandControler.GetStream();98

99
byte[] buffer = new byte[_commandControler.ReceiveBufferSize];100
int dataSize = ns.Read(buffer, 0, buffer.Length);101
string result = GetString(buffer, 0, dataSize);102

103
if (result.Length == 0)104

{105
controlInfo.ReturnCode = 0;106
controlInfo.Message = "";107
controlInfo.ReturnResult = "";108
return true;109
}110

111
controlInfo.ReturnCode = Convert.ToInt32(result.Substring(0, 3));112
controlInfo.Message = result.Substring(4);113
controlInfo.ReturnResult = result;114

115
return true;116
}117
catch(Exception e)118

{119
controlInfo.ReturnCode = 0;120
controlInfo.Message = "";121
controlInfo.ReturnResult = "";122
DisplayLocalMessage(e.Message);123
return false;124
}125
}126

127
public bool ReceiveData(ControlInfo controlInfo)128

{129
InitDataControler();130

131
Send(controlInfo);132
ReadReply(controlInfo);133
Display(controlInfo.ReturnResult);134

135
if (!controlInfo.Success)136

{137
Display( controlInfo.Parameter + " 传输失败!\n");138
return false;139
}140
try141

{142
143
int startTime = Environment.TickCount;144

145
NetworkStream ns = _dataControler.GetStream();146
string filename = controlInfo.Parameter2.Length > 0 ? controlInfo.Parameter2 : controlInfo.Parameter;147

148
FileStream fs = new FileStream(_currentDir + @"\" + filename, FileMode.Create);149
Int64 totalSize = 0;150
if (_isBinary)151

{152
byte[] buffer = new byte[1024];153

154
int dataSize = 0;155

156
BinaryWriter bw = new BinaryWriter(fs);157

158
while ((dataSize = ns.Read(buffer, 0, buffer.Length)) > 0)159

{160
totalSize += dataSize;161
bw.Write(buffer, 0, dataSize);162
}163

164
bw.Close();165
}166
else167

{168
//ArrayList datas = new ArrayList();169
//StreamWriter sw170
//while ((dataSize = ns.Read(buffer, 0, buffer.Length)) > 0)171
//{172
// //sw.Write(Encoding.UTF8.GetChars(buffer, 0, dataSize),173
// //0, dataSize);174
//}175

176
//StreamWriter sw = new StreamWriter(fs);177
//sw.Write(Encoding.UTF8.GetString(buffer, 0, dataSize));178
//Display("已传送 " + controlInfo.Parameter + " " + fs.Length + " bytes. \n");179
//sw.Close();180
}181

182
fs.Close();183
ns.Close();184
_dataControler.Close();185
ReadReply(controlInfo);186
Display(controlInfo.ReturnResult);187
double useTime = GetUseTime(startTime, Environment.TickCount);188
double speed = totalSize / useTime;189

190
Display("已传送 " + filename + " " + totalSize + " bytes, use time " +191
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\n");192

193
return true;194
}195
catch (Exception e)196

{197
DisplayLocalMessage(e.Message);198
return false;199
}200
}201

202
private void InitDataControler()203

{204
if (!_isPassive) //主动模式,等待Server的连接请求205

{206
_dataControler = _listener.AcceptTcpClient();207
}208
else209

{210
DisplayLocalMessage("正打开数据连接 IP: " + _transferEndPoint.ToString() + "\n");211
_dataControler = new TcpClient();212
_dataControler.Connect(_transferEndPoint);213
}214
}215

216
public bool ReceiveList(ControlInfo controlInfo)217

{218
InitDataControler();219

220
Send(controlInfo);221
ReadReply(controlInfo);222
Display(controlInfo.ReturnResult);223

224
if (!controlInfo.Success)225

{226
Display(controlInfo.Parameter + " 传输失败!\n");227
return false;228
}229
try230

{231
int startTime = Environment.TickCount;232
NetworkStream ns = _dataControler.GetStream();233
byte[] buffer = new byte[_dataControler.ReceiveBufferSize];234
int totalSize = 0;235
int dataSize = 0;236
StringBuilder sb = new StringBuilder();237

238

239
while ((dataSize = ns.Read(buffer, 0, _dataControler.ReceiveBufferSize)) > 0)240

{241
sb.Append(GetString(buffer, 0, dataSize));242
totalSize += dataSize;243
}244
double useTime = GetUseTime(startTime, Environment.TickCount);245
double speed = totalSize / useTime;246
if (controlInfo.Parameter.Length == 0)247

{248
Display(sb.ToString());249
}250
else251

{252
FileStream fs = new FileStream(_currentDir + @"\" + controlInfo.Parameter, FileMode.Create);253
StreamWriter sw = new StreamWriter(fs);254
sw.Write(sb.ToString());255
sw.Close();256
fs.Close();257
DisplayLocalMessage("列表已保存为: " + controlInfo.Parameter + ".\r\n");258
}259
//if(260
ReadReply(controlInfo);261
Display(controlInfo.ReturnResult);262
DisplayLocalMessage("列表完成: " + totalSize + " bytes, use time " +263
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\r\n");264

265
return true;266
}267
catch (Exception e)268

{269
DisplayLocalMessage(e.Message);270
return false;271
}272
}273

274
private void DisplayCommand(string command)275

{276
Console.ForegroundColor = ConsoleColor.Yellow;277
Console.Write(command);278
Console.ForegroundColor = ConsoleColor.White;279
}280

281
private void DisplayLocalMessage(string message)282

{283
Console.ForegroundColor = ConsoleColor.Red;284
Console.Write(message);285
Console.ForegroundColor = ConsoleColor.White;286
}287

288
private IPEndPoint GetEndPoint(string strEndPoint)289

{290
string[] endPoints = strEndPoint.Split(',');291
string remoteIP = endPoints[0] + "." + endPoints[1] + "."292
+ endPoints[2] + "." + endPoints[3];293

294
//endp[4] X 256 + endp[5];295
int port = (Convert.ToInt32(endPoints[4]) * 256) + (int.Parse(endPoints[5]));296
IPAddress ip = IPAddress.Parse(remoteIP);297
IPEndPoint remoteEP = new IPEndPoint(ip, port);298

299
return remoteEP;300
}301

302
private void Send(ControlInfo controlInfo)303

{304
DisplayCommand(controlInfo.GetCommand());305
NetworkStream ns = _commandControler.GetStream();306
byte[] sendData = GetBytes(controlInfo.GetCommand());307
ns.Write(sendData, 0, sendData.Length);308
}309

310
private void Send(string command)311

{312
DisplayCommand(command);313
NetworkStream ns = _commandControler.GetStream();314
byte[] sendData = GetBytes(command);315
ns.Write(sendData, 0, sendData.Length);316
}317

318
public void ExcuteCommand(string command)319

{320
string cmd = "";321
int index = 1;322
bool isDone = false;323
string paras = "";324
for (; index <= command.Length && !isDone; index++)325

{326
cmd = command.Substring(0, index);327
paras = command.Substring(index);328
isDone = DoCommand(cmd, paras);329
}330
if(!isDone)331
DisplayCommand("Invalid command.\r\n");332
}333

334
private bool DoCommand(string command, string parameter)335

{336
switch (command.ToLower())337

{ 338
case "get":339
SetBinaryMode(true);340
SetMode();341
Excute("RETR" + parameter);342
//FileInfo file = new FileInfo(parameter);343
//File.344
break;345
case "put":346
SetBinaryMode(true);347
SetMode();348
Excute("STOR" + parameter);349
break;350
case "dir":351
Excute("PWD");352
SetBinaryMode(false);353
SetMode();354
Excute("LIST" + parameter);355
break;356
case "pwd":357
Excute("PWD");358
break;359
case "cd":360
if (Excute("CWD" + parameter))361

{362
DoCommand("dir", "");363
}364
break;365
case "?":366
GetHelp(parameter.Trim());367
break;368
case "quit":369
Excute("QUIT");370
break;371
case "user":372
return Login(parameter);373
default:374
return false;375
}376
return true;377
}378

379
public bool Login(string usernameAndPassword)380

{381
int index = usernameAndPassword.IndexOf(" ", 1);382
_username = usernameAndPassword.Substring(0, index).Trim();383
_password = usernameAndPassword.Substring(index + 1).Trim();384
if (Excute("USER " + _username))385

{386
if (Excute("PASS " + _password))387

{388
return true;389
}390
}391
return false;392
}393

394
private void GetHelp(string para)395

{396
string message = "Invalid command.";397
switch (para)398

{ 399
case "":400
message="\t?\tget\tput\tdir\r\n\tcd\tquit";401
break;402
case "?":403
message = "? 显示 ftp 命令说明.\r\n"404
+ "格式: ? [command]\r\n"405
+ "说明: [command]指定需要帮助的命令名称.如果没有指定 command,ftp 将显示全部命令的列表.";406
break;407
case "get":408
message="get 使用当前文件转换类型将远程文件复制到本地计算机.\r\n"409
+"格式: get remote-file [local-file]\r\n"410
+"说明: remote-file 指定要复制的远程文件,\r\n"411
+"local-file 指定要在本地计算机上使用的名称,若没指定,文件将命名为remote-file.";412
break;413
case "put":414
message = "put 使用当前文件传送类型将本地文件复制到远程计算机上.\r\n"415
+ "格式: put local-file [remote-file]\r\n"416
+ "说明: local-file 指定要复制的本地文件,\r\n"417
+ "remote-file 指定要在远程计算机上使用的名称,若没指定,文件将命名为local-file.";418
break;419
case "dir":420
message = "dir 显示远程目录文件和子目录列表.\r\n"421
+ "格式: dir [remote-directory] [local-file]\r\n"422
+ "说明: remote-directory 指定要查看其列表的目录.如果没有指定目录,将使用远程计算机中的当前工作目录,\r\n"423
+ "Local-file 指定要存储列表的本地文件.如果没有指定,输出将显示在屏幕上.";424
break;425
case "cd":426
message = "cd 更改远程计算机上的工作目录.\r\n"427
+ "格式: cd remote-directory\r\n"428
+ "说明: remote-directory 指定要更改的远程计算机上的目录.";429
break;430
case "quit":431
message = "quit 结束与远程计算机的 FTP 会话并退出 ftp.\r\n"432
+ "格式: quit";433
break;434
case "user":435
message = "user 指定远程计算机的用户.\r\n"436
+ "格式: user username [password] [account]\r\n"437
+ "说明: username 指定登录到远程计算机所使用的用户名.\r\n"438
+ "password 指定 user-name 的密码.如果没有指定,但必须指定,ftp 会提示输入密码.";439
break;440
}441
DisplayCommand(message + "\r\n");442
}443

444
private bool SetMode()445

{446
if (_isPassive)447

{448
return Excute("PASV");449
}450
else451

{452
return Excute("PORT");453
}454
}455

456
public bool Excute(string command)457

{458
return Excute(ControlInfo.Create(command));459
}460

461
public bool Excute(ControlInfo controlInfo)462

{463
switch (controlInfo.Command)464

{465
//用户466
case "USER":467
Send(controlInfo);468
ReadReply(controlInfo);469
Display(controlInfo.ReturnResult);470
break;471
//密码472
case "PASS":473
Send(controlInfo);474
ReadReply(controlInfo);475
Display(controlInfo.ReturnResult);476
break;477
//EPSV478
case "EPSV":479
Send(controlInfo);480
ReadReply(controlInfo);481
Display(controlInfo.ReturnResult);482
break;483
//被动模式484
case "PASV":485
Send(controlInfo);486
ReadReply(controlInfo);487
Display(controlInfo.ReturnResult);488
if (controlInfo.Success)489

{490
_isPassive = true;491
SetTransferEndPoint(controlInfo.Message);492
}493
else494
return false;495
break;496
//设定主动模式的数据连接端口497
case "PORT":498
return StartListener(controlInfo);499
//文件及子目录列表500
case "LIST":501
return ReceiveList(controlInfo);502
//下载文件503
case "RETR":504
return ReceiveData(controlInfo);505
//名字系统类型506
case "SYST":507
Send(controlInfo);508
ReadReply(controlInfo);509
Display(controlInfo.ReturnResult);510
break;511
//上传文件512
case "STOR":513
return SendData(controlInfo);514
//改变工作目录515
case "CWD":516
Send(controlInfo);517
ReadReply(controlInfo);518
Display(controlInfo.ReturnResult);519
if (controlInfo.Success)520

{521
SetServerDir(controlInfo.Message);522
}523
else524

{525
return false;526
}527
break;528
//当前目录529
case "PWD":530
Send(controlInfo);531
ReadReply(controlInfo);532
Display(controlInfo.ReturnResult);533
break;534
//传输模式535
case "TYPE":536
Send(controlInfo);537
ReadReply(controlInfo);538
Display(controlInfo.ReturnResult);539
if (controlInfo.Success)540

{541
switch (controlInfo.Parameter)542

{543
case "I":544
_isBinary = true;545
break;546
case "A":547
_isBinary = false;548
break;549
}550
}551
break;552
//退出553
case "QUIT":554
Send(controlInfo);555
ReadReply(controlInfo);556
Display(controlInfo.ReturnResult);557
Close();558
break;559
default:560
Display("This is '" + controlInfo.Command + "' not implemented.\n");561
return false;562
}563
return true;564
}565

566
private void SetServerDir(string dir)567

{568
int startIndex = dir.IndexOf("to ") + 3;569
int length = dir.LastIndexOf("\r\n") - startIndex;570
_serverDir = dir.Substring(startIndex, length);571
}572

573
private bool SendData(ControlInfo controlInfo)574

{575
if (controlInfo.Parameter2.Length > 0)576

{577
Send(controlInfo.Command + " " + controlInfo.Parameter2 + "\r\n");578
}579
else580

{581
Send(controlInfo);582
}583
ReadReply(controlInfo);584
Display(controlInfo.ReturnResult);585

586
if (!controlInfo.Success)587

{588
Display("传送失败!\r\n");589
return false;590
}591
InitDataControler();592

593
try594

{595
int startTime = Environment.TickCount;596

597
string file = _currentDir + @"\" + controlInfo.Parameter;598
FileInfo fileInfo = new FileInfo(file);599
if (!fileInfo.Exists)600

{601
Display(fileInfo.FullName + " : No such file.\r\n");602
_dataControler.Close();603
return false;604
}605
if (_isBinary)606

{607
_dataControler.Client.SendFile(file);608
609
}610
else611

{612
FileStream fs = new FileStream(fileInfo.FullName, FileMode.Open);613
StreamReader sr = new StreamReader(fs);614
byte[] buffer = GetBytes(sr.ReadToEnd());615
_dataControler.GetStream().Write(buffer, 0, buffer.Length);616
sr.Close();617
fs.Close();618
}619
_dataControler.Close();620

621
controlInfo.SuccessCode = 226;622
ReadReply(controlInfo);623
Display(controlInfo.ReturnResult);624
double useTime = GetUseTime(startTime, Environment.TickCount);625
double speed = fileInfo.Length / useTime;626

627
if (controlInfo.Success)628

{629
Display("已传送 " + controlInfo.Parameter + " " + fileInfo.Length + " bytes, use time " +630
useTime.ToString("f2") + " Seconds (" + GetSpeed(speed) + ").\n");631
//Display("已传数: " + controlInfo.Parameter + " " + fileInfo.Length + " bytes.\n");632
}633
else634

{635
Display(controlInfo.Parameter + " 传送失败!\r\n");636
}637
return true;638
}639
catch (Exception e)640

{641
DisplayLocalMessage(e.Message);642
return false;643
}644
}645

646
private void SetTransferEndPoint(string endPoint)647

{648
int offset = endPoint.IndexOf("(") + 1;649
int length = endPoint.LastIndexOf(")") - offset;650
endPoint = endPoint.Substring(offset, length);651
_transferEndPoint = GetEndPoint(endPoint);652
}653

654

/**//// <summary>655
/// 计算传输时间,以秒为单位656
/// </summary>657
/// <param name="startTime">开始的毫秒数</param>658
/// <param name="endTime">结束的毫秒数</param>659
/// <returns></returns>660
private double GetUseTime(int startTime, int endTime)661

{662
double useTime = ((double)(endTime - startTime)) / 1000;663
if (useTime == 0)664

{665
useTime = 0.01;666
}667
return useTime;668
}669

670
private string GetSpeed(double speed)671

{672
string unit = " Bytes/S";673
if (speed > 1000)674

{675
speed = speed / 1000;676
unit = " KB/S";677
}678
if (speed > 1000)679

{680
speed = speed / 1000;681
unit = " MB/S";682
}683
if (speed > 1000)684

{685
speed /= 1000;686
unit = " GB/S";687
}688
return speed.ToString("f2") + unit;689
}690

691
private bool StartListener(ControlInfo controlInfo)692

{693
int p = controlInfo.Parameter.Length > 0 ? Convert.ToInt32(controlInfo.Parameter) : 0;694
IPEndPoint localEP = new IPEndPoint(_clientIP, p);695
_listener = new TcpListener(localEP);696
_listener.Start();697
DisplayLocalMessage("已打开数据监听连接 IP:" + _listener.LocalEndpoint.ToString() + "\r\n");698
//CultureInfo ci = (CultureInfo)Thread.CurrentThread.CurrentCulture.Clone();699
//NumberFormatInfo nfi = ci.NumberFormat;700

/**/////Set our format to "123,456"701
//nfi.CurrencyPositivePattern = 1;702
//nfi.CurrencyGroupSeparator = ",";703
//nfi.CurrencySymbol = "";704
//nfi.CurrencyDecimalDigits = 0;705
//ci.NumberFormat = nfi;706

707
//Thread.CurrentThread.CurrentCulture = ci;708
localEP = (IPEndPoint)_listener.LocalEndpoint;709

710
string ip = localEP.Address.ToString().Replace(".", ",");711
//string port = localEP.Port.ToString("C");712
int p1 = localEP.Port / 256;713
int p2 = localEP.Port % 256;714
controlInfo.Parameter = ip + "," + p1 + "," + p2;715

716
Send(controlInfo);717
ReadReply(controlInfo);718
Display(controlInfo.ReturnResult);719
if (controlInfo.Success)720

{721
_isPassive = false;722
}723
else724
return false;725
return true;726
}727

728
private void Display(string str)729

{730
Console.ForegroundColor = ConsoleColor.Green;731
Console.Write(str);732
Console.ForegroundColor = ConsoleColor.White;733
}734

735

/**//// <summary>736
/// 将字符串转换成UTF8码的字节数组,这样可以传输中文等737
/// </summary>738
/// <param name="response"></param>739
/// <returns></returns>740
private byte[] GetBytes(string response)741

{742
return GetBytes(response, Encoding.Default);743
}744

745
private byte[] GetBytes(string response, Encoding encoder)746

{747
return encoder.GetBytes(response.ToCharArray());748
}749

750
//private void Append(StringBuilder sb, byte[] data)751
//{752
// sb.Append(Encoding.Default.GetString(data));753
//}754

755
private string GetString(byte[] datas)756

{757
return GetString(datas, 0, datas.Length);758
}759

760
private string GetString(byte[] datas, int offset, int size)761

{762
return GetString(datas, offset, size, Encoding.Default);763
}764

765
private string GetString(byte[] datas, int offset, int size, Encoding encoder)766

{767
return encoder.GetString(datas, offset, size);768
}769
}770
}771

代码未经整理,呵呵,等寒假再回来重构一下.


浙公网安备 33010602011771号