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

 

 

 

你可能感兴趣的:(socket)