美奇科技 发表于 2015-5-26 09:50:24

Ftp协议Socket实现

  原来用WebRequest来传输文件,被人鄙视了。就弄个Socket版的,支持Active,Passive模式。
  带事件日志,有时间的人可以拿去做C#版的flashfxp。





1 public class FtpClient
2   {
3         public class FtpLogEventArgs : EventArgs
4         {
5             private string mStrLog = string.Empty;
6             public string Log
7             {
8               get
9               {
10                     return this.mStrLog;
11               }
12             }
13             public FtpLogEventArgs(string strLog)
14             {
15               this.mStrLog = strLog;
16             }
17         }
18         public delegate void FtpLogEventHandler(object sender, FtpLogEventArgs e);
19         public class FtpTranProgressEventArgs : EventArgs
20         {
21             private uint mPercent = 0u;
22             private bool mCancel = false;
23             public uint Percent
24             {
25               get
26               {
27                     return this.mPercent;
28               }
29             }
30             public bool Cancel
31             {
32               get
33               {
34                     return this.mCancel;
35               }
36               set
37               {
38               }
39             }
40             public FtpTranProgressEventArgs(uint percent)
41             {
42               this.mPercent = percent;
43               this.mCancel = false;
44             }
45         }
46         public delegate void FtpTranProgressEventHandler(object sender, FtpTranProgressEventArgs e);
47         public enum FtpTransferType
48         {
49             Binary,
50             ASCII
51         }
52         public enum FtpMode
53         {
54             Active,
55             Passive
56         }
57         public enum FtpSystemType
58         {
59             UNIX,
60             WINDOWS
61         }
62         private Socket mSocketConnect = null;
63         private string mStrServer = string.Empty;
64         private int mIntPort = 21;
65         private string mStrUser = string.Empty;
66         private string mStrPassword = string.Empty;
67         private string mStrPath = string.Empty;
68         private bool mIsConnected = false;
69         private FtpMode mMode = FtpMode.Passive;
70         private FtpSystemType mSystemType = FtpSystemType.UNIX;
71         private string mStrReply = string.Empty;
72         private int mIntReplyCode = 0;
73         private static int BLOCK_SIZE = 2048;
74         private byte[] mBuffer = new byte;
75
76         private event FtpLogEventHandler mFtpLogEvent;
77         public event FtpLogEventHandler FtpLogEvent
78         {
79             add
80             {
81               FtpLogEventHandler handlerTemp;
82               FtpLogEventHandler fieldsChanged = this.mFtpLogEvent;
83               do
84               {
85                     handlerTemp = fieldsChanged;
86                     FtpLogEventHandler handlerRes = (FtpLogEventHandler)Delegate.Combine(handlerTemp, value);
87                     fieldsChanged = Interlocked.CompareExchange(ref this.mFtpLogEvent, handlerRes, handlerTemp);
88               }
89               while (fieldsChanged != handlerTemp);
90             }
91
92             remove
93             {
94               FtpLogEventHandler handlerTemp;
95               FtpLogEventHandler fieldsChanged = this.mFtpLogEvent;
96               do
97               {
98                     handlerTemp = fieldsChanged;
99                     FtpLogEventHandler handlerRes = (FtpLogEventHandler)Delegate.Remove(handlerTemp, value);
100                     fieldsChanged = Interlocked.CompareExchange(ref this.mFtpLogEvent, handlerRes, handlerTemp);
101               }
102               while (fieldsChanged != handlerTemp);
103             }
104         }
105
106         private event FtpTranProgressEventHandler mFtpTranProgressEvent;
107         public event FtpTranProgressEventHandler FtpTranProgressEvent
108         {
109             add
110             {
111               FtpTranProgressEventHandler handlerTemp;
112               FtpTranProgressEventHandler fieldsChanged = this.mFtpTranProgressEvent;
113               do
114               {
115                     handlerTemp = fieldsChanged;
116                     FtpTranProgressEventHandler handlerRes = (FtpTranProgressEventHandler)Delegate.Combine(handlerTemp, value);
117                     fieldsChanged = Interlocked.CompareExchange(ref this.mFtpTranProgressEvent, handlerRes, handlerTemp);
118               }
119               while (fieldsChanged != handlerTemp);
120             }
121             remove
122             {
123               FtpTranProgressEventHandler handlerTemp;
124               FtpTranProgressEventHandler fieldsChanged = this.mFtpTranProgressEvent;
125               do
126               {
127                     handlerTemp = fieldsChanged;
128                     FtpTranProgressEventHandler handlerRes = (FtpTranProgressEventHandler)Delegate.Remove(handlerTemp, value);
129                     fieldsChanged = Interlocked.CompareExchange(ref this.mFtpTranProgressEvent, handlerRes, handlerTemp);
130               }
131               while (fieldsChanged != handlerTemp);
132             }
133         }
134         public bool Connected
135         {
136             get
137             {
138               return this.mIsConnected;
139             }
140         }
141         public FtpTransferType TransferType
142         {
143             set
144             {
145               if (value == FtpTransferType.Binary)
146               {
147                     this.SendCommand("TYPE I");
148               }
149               else
150               {
151                     this.SendCommand("TYPE A");
152               }
153               if (this.mIntReplyCode != 200)
154               {
155                     throw new IOException(this.mStrReply.Substring(4));
156               }
157             }
158         }
159         public FtpMode Mode
160         {
161             get
162             {
163               return this.mMode;
164             }
165             set
166             {
167               this.mMode = value;
168             }
169         }
170         public FtpSystemType SystemType
171         {
172             get
173             {
174               return this.mSystemType;
175             }
176             set
177             {
178               this.mSystemType = value;
179             }
180         }
181         protected virtual void OnFtpLogEvent(FtpLogEventArgs e)
182         {
183             if (this.mFtpLogEvent != null)
184             {
185               this.mFtpLogEvent(this, e);
186             }
187         }
188         protected virtual void OnFtpTranProgressEvent(FtpTranProgressEventArgs e)
189         {
190             if (this.mFtpTranProgressEvent != null)
191             {
192               this.mFtpTranProgressEvent(this, e);
193             }
194         }
195         public FtpClient(string server, string path, string user, string password, int port, FtpClient.FtpMode mode)
196         {
197             this.mStrServer = server;
198             this.mStrPath = path;
199             this.mStrUser = user;
200             this.mStrPassword = password;
201             this.mIntPort = port;
202             this.mMode = mode;
203         }
204         public void Connect()
205         {
206             this.mSocketConnect = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
207             IPHostEntry ipHost = Dns.GetHostEntry(this.mStrServer);
208             IPEndPoint iPEndPoint = new IPEndPoint(ipHost.AddressList, this.mIntPort);
209             try
210             {
211               this.mSocketConnect.Connect(iPEndPoint);
212             }
213             catch (Exception)
214             {
215               throw new IOException("Couldn't connect to remote server");
216             }
217             this.ReadReply();
218             if (this.mIntReplyCode != 220)
219             {
220               this.DisConnect();
221               throw new IOException(this.mStrReply.Substring(4));
222             }
223             this.SendCommand("USER " + this.mStrUser);
224             if (this.mIntReplyCode != 331 && this.mIntReplyCode != 230)
225             {
226               this.CloseSocketConnect();
227               throw new IOException(this.mStrReply.Substring(4));
228             }
229             if (this.mIntReplyCode == 331)
230             {
231               this.SendCommand("PASS " + this.mStrPassword);
232               if (this.mIntReplyCode != 230 && this.mIntReplyCode != 202)
233               {
234                     this.CloseSocketConnect();
235                     throw new IOException(this.mStrReply.Substring(4));
236               }
237             }
238             this.SendCommand("SYST");
239             if (this.mIntReplyCode != 215)
240             {
241               this.CloseSocketConnect();
242               throw new IOException(this.mStrReply.Substring(4));
243             }
244
245             if (this.mStrReply.ToString() == "W" || this.mStrReply.ToString() == "w")
246             {
247               this.mSystemType = FtpClient.FtpSystemType.WINDOWS;
248             }
249             this.mIsConnected = true;
250             this.ChDir(this.mStrPath);
251         }
252         public void DisConnect()
253         {
254             this.CloseSocketConnect();
255         }
256         public void ChDir(string strDirName)
257         {
258             if (strDirName.Equals(""))
259             {
260               return;
261             }
262             if (!this.mIsConnected)
263             {
264               this.Connect();
265             }
266             this.SendCommand("CWD " + strDirName);
267             if (this.mIntReplyCode != 250)
268             {
269               throw new IOException(this.mStrReply.Substring(4));
270             }
271             this.mStrPath = strDirName;
272         }
273         public void Reset(long size)
274         {
275             if (!this.mIsConnected)
276             {
277               this.Connect();
278             }
279             this.SendCommand("REST " + size.ToString());
280             if (this.mIntReplyCode != 350)
281             {
282               throw new IOException(this.mStrReply.Substring(4));
283             }
284         }
285         public string[] Dir(string strMark)
286         {
287             if (!this.mIsConnected)
288             {
289               this.Connect();
290             }
291             char[] array = new char[]
292             {
293               '\n'
294             };
295             string text;
296             string[] result;
297             if (this.mMode == FtpClient.FtpMode.Active)
298             {
299               TcpListener tcpListener = null;
300               this.CreateDataListener(ref tcpListener);
301               this.TransferType = FtpClient.FtpTransferType.ASCII;
302               this.SendCommand("LIST");
303               Socket socket = tcpListener.AcceptSocket();
304               text = "";
305               int num;
306               do
307               {
308                     num = socket.Receive(this.mBuffer, this.mBuffer.Length, 0);
309                     text += Encoding.Default.GetString(this.mBuffer, 0, num);
310               }
311               while (num >= this.mBuffer.Length);
312               result = text.Split(array);
313               socket.Close();
314               tcpListener.Stop();
315               return result;
316             }
317             Socket socket2 = this.CreateDataSocket();
318             this.SendCommand("LIST");
319             if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226)
320             {
321               throw new IOException(this.mStrReply.Substring(4));
322             }
323             text = "";
324             int num2;
325             do
326             {
327               num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, 0);
328               text += Encoding.Default.GetString(this.mBuffer, 0, num2);
329             }
330             while (num2 >= this.mBuffer.Length);
331             result = text.Split(array);
332             socket2.Close();
333             if (this.mIntReplyCode != 226)
334             {
335               this.ReadReply();
336               if (this.mIntReplyCode != 226)
337               {
338                     throw new IOException(this.mStrReply.Substring(4));
339               }
340             }
341             return result;
342         }
343         public void UploadFile(string strFile)
344         {
345             if (!this.mIsConnected)
346             {
347               this.Connect();
348             }
349             if (this.mMode == FtpClient.FtpMode.Active)
350             {
351               TcpListener tcpListener = null;
352               this.CreateDataListener(ref tcpListener);
353               this.TransferType = FtpClient.FtpTransferType.Binary;
354               this.SendCommand("STOR " + Path.GetFileName(strFile));
355               if (this.mIntReplyCode != 125 && this.mIntReplyCode != 150)
356               {
357                     throw new IOException(this.mStrReply.Substring(4));
358               }
359               Socket socket = tcpListener.AcceptSocket();
360               FileStream fileStream = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
361               long length = fileStream.Length;
362               long num = 0L;
363               int num2;
364               while ((num2 = fileStream.Read(this.mBuffer, 0, this.mBuffer.Length)) > 0)
365               {
366                     num += (long)num2;
367                     uint percent = (uint)(num * 100L / length);
368                     FtpClient.FtpTranProgressEventArgs e = new FtpClient.FtpTranProgressEventArgs(percent);
369                     this.OnFtpTranProgressEvent(e);
370                     socket.Send(this.mBuffer, num2, 0);
371               }
372               fileStream.Close();
373               if (socket.Connected)
374               {
375                     socket.Close();
376               }
377               tcpListener.Stop();
378               return;
379             }
380             else
381             {
382               Socket socket2 = this.CreateDataSocket();
383               this.SendCommand("STOR " + Path.GetFileName(strFile));
384               if (this.mIntReplyCode != 125 && this.mIntReplyCode != 150)
385               {
386                     throw new IOException(this.mStrReply.Substring(4));
387               }
388               FileStream fileStream2 = new FileStream(strFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
389               long length = fileStream2.Length;
390               long num = 0L;
391               int num2;
392               while ((num2 = fileStream2.Read(this.mBuffer, 0, this.mBuffer.Length)) > 0)
393               {
394                     num += (long)num2;
395                     uint percent = (uint)(num * 100L / length);
396                     FtpClient.FtpTranProgressEventArgs e2 = new FtpClient.FtpTranProgressEventArgs(percent);
397                     this.OnFtpTranProgressEvent(e2);
398                     socket2.Send(this.mBuffer, num2, 0);
399               }
400               fileStream2.Close();
401               if (socket2.Connected)
402               {
403                     socket2.Close();
404               }
405               if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
406               {
407                     this.ReadReply();
408                     if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
409                     {
410                         throw new IOException(this.mStrReply.Substring(4));
411                     }
412               }
413               return;
414             }
415         }
416         public void DownloadFile(string strRemoteFileName, string strLocalFolder, string strLocalFileName)
417         {
418             if (!this.mIsConnected)
419             {
420               this.Connect();
421             }
422             if (this.mMode == FtpClient.FtpMode.Active)
423             {
424               TcpListener tcpListener = null;
425               this.CreateDataListener(ref tcpListener);
426               string extension = Path.GetExtension(strRemoteFileName);
427               if (extension != ".txt" && extension != ".TXT")
428               {
429                     this.TransferType = FtpClient.FtpTransferType.Binary;
430               }
431               if (strLocalFileName == "")
432               {
433                     strLocalFileName = strRemoteFileName;
434               }
435               FileStream fileStream = new FileStream(strLocalFolder + "\\" + strLocalFileName, FileMode.Create);
436               this.SendCommand("RETR " + strRemoteFileName);
437               if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226 && this.mIntReplyCode != 250 && this.mIntReplyCode != 200)
438               {
439                     fileStream.Close();
440                     throw new IOException(this.mStrReply.Substring(4));
441               }
442               Socket socket = tcpListener.AcceptSocket();
443               while (true)
444               {
445                     int num = socket.Receive(this.mBuffer, this.mBuffer.Length, 0);
446                     if (num2)
584             {
585               text = array2;
586             }
587             else
588             {
589               text = array2;
590             }
591             if (!text.Substring(3, 1).Equals(" "))
592             {
593               return this.ReadLine();
594             }
595             return text;
596         }
597         private void ReadReply()
598         {
599             this.mStrReply = this.ReadLine();
600             this.mIntReplyCode = int.Parse(this.mStrReply.Substring(0, 3));
601         }
602         private void SendCommand(string strCommand)
603         {
604             FtpLogEventArgs e = new FtpLogEventArgs("命令:" + strCommand);
605             this.OnFtpLogEvent(e);
606             byte[] bytes = Encoding.Default.GetBytes((strCommand + "\r\n").ToCharArray());
607             this.mSocketConnect.Send(bytes, bytes.Length, 0);
608             this.ReadReply();
609         }
610         private void CloseSocketConnect()
611         {
612             if (this.mSocketConnect != null)
613             {
614               this.mSocketConnect.Close();
615               this.mSocketConnect = null;
616             }
617             this.mIsConnected = false;
618         }
619         private Socket CreateDataSocket()
620         {
621             Socket result;
622             try
623             {
624               this.SendCommand("PASV");
625               if (this.mIntReplyCode != 227)
626               {
627                     throw new IOException(this.mStrReply.Substring(4));
628               }
629               int num = this.mStrReply.IndexOf('(');
630               int num2 = this.mStrReply.IndexOf(')');
631               string text = this.mStrReply.Substring(num + 1, num2 - num - 1);
632               string[] array = new string;
633               array = text.Split(new char[]
634               {
635                     ','
636               });
637               if (array.Length != 6)
638               {
639                     throw new IOException("Malformed PASV strReply: " + this.mStrReply);
640               }
641               string text2 = string.Concat(new string[]
642               {
643                     array,
644                     ".",
645                     array,
646                     ".",
647                     array,
648                     ".",
649                     array
650               });
651               try
652               {
653                     num = int.Parse(array);
654                     num2 = int.Parse(array);
655               }
656               catch
657               {
658                     throw new IOException("Malformed PASV strReply: " + this.mStrReply);
659               }
660               int num3 = (num > 8;
687             int num2 = iPEndPoint.Port & 255;
688             this.SendCommand(string.Concat(new string[]
689             {
690               "PORT ",
691               iPEndPoint.Address.ToString().Replace(".", ","),
692               ",",
693               num.ToString(),
694               ",",
695               num2.ToString()
696             }));
697             if (this.mIntReplyCode != 200 && this.mIntReplyCode != 226)
698             {
699               throw new IOException(this.mStrReply.Substring(4));
700             }
701         }
702   }
View Code   简单使用





1 FtpClient ftpClient = new FtpClient(ip, "/", user, pass, 21, FtpClient.FtpMode.Passive);
2 ftpClient.FtpTranProgressEvent += (s, e) =>
3 {
4   progress.Value = (int)e.Percent;
5   Application.DoEvents();
6 };
7
8 try
9 {
10   ftpClient.Connect();
11 }
12 catch (Exception ex)
13 {
14   ftpClient = null;
15   return;
16 }
17
18   if (ftpClient.Connected)
19   {
20     ftpClient.CreateDir(root);
21     ftpClient.ChDir(root);
22
23   try
24   {
25     ftpClient.UploadFile(@"D:\shin_angyo_onshi\Vol_SP\001.jpg");
26   }
27   catch (Exception ex)
28   {
29     MessageBox.Show(ex.Message.ToString());
30     return;
31   }
32 }
View Code   
  
  
页: [1]
查看完整版本: Ftp协议Socket实现