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[FtpClient.BLOCK_SIZE];
 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<FtpLogEventHandler>(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<FtpLogEventHandler>(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<FtpTranProgressEventHandler>(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<FtpTranProgressEventHandler>(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[0], 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[4].ToString() == "W" || this.mStrReply[4].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 (num <= 0)
447                     {
448                         break;
449                     }
450                     fileStream.Write(this.mBuffer, 0, num);
451                 }
452                 fileStream.Close();
453                 if (socket.Connected)
454                 {
455                     socket.Close();
456                 }
457                 if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
458                 {
459                     this.ReadReply();
460                     if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
461                     {
462                         throw new IOException(this.mStrReply.Substring(4));
463                     }
464                 }
465                 tcpListener.Stop();
466                 return;
467             }
468             else
469             {
470                 string extension2 = Path.GetExtension(strRemoteFileName);
471                 if (extension2 != ".txt" && extension2 != ".TXT")
472                 {
473                     this.TransferType = FtpClient.FtpTransferType.Binary;
474                 }
475                 if (strLocalFileName == "")
476                 {
477                     strLocalFileName = strRemoteFileName;
478                 }
479                 FileStream fileStream2 = new FileStream(strLocalFolder + "\\" + strLocalFileName, FileMode.Create);
480                 Socket socket2 = this.CreateDataSocket();
481                 this.SendCommand("RETR " + strRemoteFileName);
482                 if (this.mIntReplyCode != 150 && this.mIntReplyCode != 125 && this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
483                 {
484                     fileStream2.Close();
485                     throw new IOException(this.mStrReply.Substring(4));
486                 }
487                 while (true)
488                 {
489                     int num2 = socket2.Receive(this.mBuffer, this.mBuffer.Length, 0);
490                     if (num2 <= 0)
491                     {
492                         break;
493                     }
494                     fileStream2.Write(this.mBuffer, 0, num2);
495                 }
496                 fileStream2.Close();
497                 if (socket2.Connected)
498                 {
499                     socket2.Close();
500                 }
501                 if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
502                 {
503                     this.ReadReply();
504                     if (this.mIntReplyCode != 226 && this.mIntReplyCode != 250)
505                     {
506                         throw new IOException(this.mStrReply.Substring(4));
507                     }
508                 }
509                 return;
510             }
511         }
512 
513         public void CreateDir(string strDirName)
514         {
515             if (!this.mIsConnected)
516             {
517                 this.Connect();
518             }
519             this.SendCommand("MKD " + strDirName);
520             if (this.mIntReplyCode != 257)
521             {
522                 throw new IOException(this.mStrReply.Substring(4));
523             }
524         }
525 
526         public void DeleteDir(string strDirName)
527         {
528             if (!this.mIsConnected)
529             {
530                 this.Connect();
531             }
532             this.SendCommand("RMD " + strDirName);
533             if (this.mIntReplyCode != 250)
534             {
535                 throw new IOException(this.mStrReply.Substring(4));
536             }
537         }
538 
539         public void DeleteFile(string strFile)
540         {
541             if (!this.mIsConnected)
542             {
543                 this.Connect();
544             }
545             this.SendCommand("DELE " + strFile);
546             if (this.mIntReplyCode != 250)
547             {
548                 throw new IOException(this.mStrReply.Substring(4));
549             }
550         }
551         private long GetFileSize(string strFileName)
552         {
553             if (!this.mIsConnected)
554             {
555                 this.Connect();
556             }
557             this.SendCommand("SIZE " + Path.GetFileName(strFileName));
558             if (this.mIntReplyCode == 213 || this.mIntReplyCode == 200)
559             {
560                 return long.Parse(this.mStrReply.Substring(4));
561             }
562             throw new IOException(this.mStrReply.Substring(4));
563         }
564         private string ReadLine()
565         {
566             string text = string.Empty;
567             Thread.Sleep(200);
568             int num;
569             do
570             {
571                 text = "";
572                 num = this.mSocketConnect.Receive(this.mBuffer, this.mBuffer.Length, 0);
573                 text += Encoding.Default.GetString(this.mBuffer, 0, num);
574                 FtpLogEventArgs e = new FtpLogEventArgs("应答:  " + text);
575                 this.OnFtpLogEvent(e);
576             }
577             while (num >= this.mBuffer.Length);
578             char[] array = new char[]
579             {
580                 '\n'
581             };
582             string[] array2 = text.Split(array);
583             if (text.Length > 2)
584             {
585                 text = array2[array2.Length - 2];
586             }
587             else
588             {
589                 text = array2[0];
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[6];
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[0],
644                     ".",
645                     array[1],
646                     ".",
647                     array[2],
648                     ".",
649                     array[3]
650                 });
651                 try
652                 {
653                     num = int.Parse(array[4]);
654                     num2 = int.Parse(array[5]);
655                 }
656                 catch
657                 {
658                     throw new IOException("Malformed PASV strReply: " + this.mStrReply);
659                 }
660                 int num3 = (num << 8) + num2;
661                 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
662                 IPEndPoint iPEndPoint = new IPEndPoint(IPAddress.Parse(text2), num3);
663                 try
664                 {
665                     socket.Connect(iPEndPoint);
666                 }
667                 catch (Exception)
668                 {
669                     throw new IOException("Can't connect to remote server");
670                 }
671                 result = socket;
672             }
673             catch (Exception ex)
674             {
675                 throw new Exception(ex.ToString());
676             }
677             return result;
678         }
679         private void CreateDataListener(ref TcpListener listener)
680         {
681             string hostName = Dns.GetHostName();
682             IPAddress iPAddress = Dns.GetHostEntry(hostName).AddressList[0];
683             listener = new TcpListener(iPAddress, 0);
684             listener.Start();
685             IPEndPoint iPEndPoint = (IPEndPoint)listener.LocalEndpoint;
686             int num = iPEndPoint.Port >> 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

 

 

 

posted @ 2013-09-03 16:09  Kurodo  阅读(4211)  评论(2编辑  收藏  举报