2017-10-31 16 views
6

Tôi đang phát triển Máy chủ FTP với Delphi XE 6 và Indy10. Vấn đề là tôi cần phải hạn chế tốc độ tải xuống (phải được cấu hình Ex. 1 KB/s, 1 MB/s, vv) và tôi không làm cho nó hoạt động. Tôi biết một số đạo cụ như BitsPerSec, vv nhưng điều này chỉ ảnh hưởng đến trao đổi dữ liệu giao thức, không phải trao đổi tập tin với lệnh RETR. Tôi thấy trong IdFTPServer.pass và Stream được chuyển đổi thành chuỗi và gửi với một vòng lặp lặp lại/cho đến khi (với IOHandler.Write()) nhưng tôi cần một số hình thức kiểm soát quá trình tải lên/tải xuống và có thể giới hạn tốc độ cho tất cả các kết nối máy khách đến. Một số giúp đỡ để đạt được điều này xin vui lòng ?.Cách giới hạn tốc độ của các tệp đã truy xuất bằng IndyFtpServer (v10)

PD: Xin lỗi vì tiếng anh nghèo của tôi.

tôi cố gắng thực hiện một CommandHandler cho lệnh RETR với mã này:

procedure TForm1.IdFTPServer1CommandHandlers0Command(ASender: TIdCommand); 
var 
    LContext : TIdFTPServerContext; 
    vStream: TFileStream; 
    path: String; 
    vX: Integer; 
    LEncoding: IIdTextEncoding; 
begin 

    LEncoding := IndyTextEncoding_8Bit; 
    LContext := ASender.Context as TIdFTPServerContext; 
    path := 'D:\indy_in_depth.pdf'; 


    try 
    vStream := TFileStream.Create(path, fmOpenRead); 
    //LContext.DataChannel.FtpOperation := ftpRetr; 
    //LContext.DataChannel.Data := VStream; 
    LContext.DataChannel.OKReply.SetReply(226, RSFTPDataConnClosed); 
    LContext.DataChannel.ErrorReply.SetReply(426, RSFTPDataConnClosedAbnormally); 

    ASender.Reply.SetReply(150, RSFTPDataConnToOpen); 
    ASender.SendReply; 

    Memo1.Lines.Add('Sending a file with: ' + IntToStr(vStream.Size) + ' bytes'); 
    //Make control of speed here ! 
    for vX := 1 to vStream.Size do 
     begin 
     vStream.Position := vX; 
     LContext.Connection.IOHandler.Write(vStream, 1, False); 
     if vX mod 10000 = 0 then 
      Memo1.Lines.Add('Sended byte: ' + IntToStr(vX)); 
     end; 

    //LContext.DataChannel.InitOperation(False); 

    //LContext.Connection.IOHandler.Write(vStream); 

    //LContext.KillDataChannel; 
    LContext.Connection.Socket.Close; 

    VStream.Free; 
    except 
    on E: Exception do 
    begin 
     ASender.Reply.SetReply(550, E.Message); 
    end; 
    end; 

end; 

Nhưng Filezilla FTP dữ liệu khách hàng cho thấy dòng như một phần của lệnh khác.

Filezilla Client

Trả lời

11

Vấn đề là tôi cần phải hạn chế tốc độ của tải (phải được cấu hình Ex. 1 KB/s, 1 MB/s, vv) và tôi không làm cho nó hoạt . Tôi biết một số đạo cụ như BitsPerSec, v.v. nhưng điều này chỉ ảnh hưởng đến trao đổi dữ liệu giao thức, chứ không phải trao đổi tệp với lệnh RETR.

BitsPerSec là một thuộc tính của lớp TIdInterceptThrottler (cùng với RecvBitsPerSecSendBitsPerSec tài sản). Một thể hiện của lớp đó có thể được gán cho bất kỳ đối tượng TIdTCPConnection nào thông qua thuộc tính Intercept của nó. Điều này không chỉ giới hạn ở kết nối lệnh, nó cũng có thể được sử dụng cho các kết nối truyền tải.

Bạn có thể truy cập vào đối tượng TIdTCPConnection của một chuyển tập tin trong TIdFTPServer qua TIdFTPServerContext.DataChannel.FDataChannel thành viên, chẳng hạn như trong trường hợp OnRetrieveFile:

type 
    // the TIdDataChannel.FDataChannel member is 'protected', 
    // so use an accessor class to reach it... 
    TIdDataChannelAccess = class(TIdDataChannel) 
    end; 

procedure TForm1.IdFTPServer1RetrieveFile(ASender: TIdFTPServerContext; 
    const AFileName: TIdFTPFileName; var VStream: TStream); 
var 
    Conn: TIdTCPConnection; 
begin 
    Conn := TIdDataChannelAccess(ASender.DataChannel).FDataChannel; 
    if Conn.Intercept = nil then 
    Conn.Intercept := TIdInterceptThrottler.Create(Conn); 
    TIdInterceptThrottler(Conn.Intercept).BitsPerSec := ...; 
    VStream := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyWrite); 
end; 

Một cách khác là tạo riêng T(File)Stream lớp được thừa kế của bạn để ghi đè lên các ảo Read()Write() các phương pháp để thực hiện điều chỉnh của riêng bạn khi cần, sau đó gán một thể hiện của lớp đó cho thông số VStream của các sự kiện OnRetrieveFileOnStoreFile.

tôi thấy trong IdFTPServer.pas, và Stream được chuyển thành chuỗi và gửi với một lặp lại/cho đến khi vòng lặp (với IOHandler.Write())

Không, một dòng suối không được quy đổi thành một chuỗi . Bạn đang đọc sai mã. Nội dung của luồng được gửi dưới dạng dữ liệu nhị phân trong một cuộc gọi đến phương thức IOHandler.Write(TStream).

nhưng tôi cần một số hình thức kiểm soát quá trình tải lên/tải xuống và có thể giới hạn tốc độ cho tất cả các kết nối khách hàng đến.

Xem ở trên.

tôi cố gắng thực hiện một CommandHandler cho lệnh RETR

Bạn KHÔNG nên được xử lý RETR lệnh trực tiếp. TIdFTPServer đã làm điều đó cho bạn. Bạn có nghĩa là sử dụng sự kiện OnRetrieveFile thay vì chuẩn bị nội dung tải xuống và sự kiện OnStoreFile để tải lên.

+1

Bạn là người tốt nhất. Tôi làm một số sai lầm khi đọc mã, nhưng đây chỉ là những gì tôi cần. Tôi đang làm việc 5 giờ sáng, vì vậy mắt và não trong điều kiện xấu lol. Tôi làm một số Throttle với bạn lớp BufferedFileStream tuyệt vời (với một số calc và một số giấc ngủ). Nhưng bây giờ tôi thấy điều này và là cách hoàn hảo. Cảm ơn rất nhiều lần nữa! Với đại diện này tôi không thể tạo nên phiếu bầu. – WoNDeR

Các vấn đề liên quan