根据客户

时间:2017-05-17 20:45:51

标签: delphi-7 tcpclient indy tcpserver

如果执行客户端请求,我试图通过TCP服务器发送文本文件。互联网上的例子要么过时,要么没用。我知道我应该使用一个流,但我不明白该怎么做。

我修改了我在互联网上找到的代码,但我对这个流感到困惑。有人可以指导我朝正确的方向发展吗?

服务器:

TForm2.bStartClick(Sender: TObject);
begin
  if not IdTCPServer1.Active then
  begin
    IdTCPServer1.Active := True;
    Log('Server started on port ' + IntToStr(IdTCPServer1.DefaultPort));
    bStart.Enabled := False;
    bStop.Enabled := True;
  end;
end;

procedure TForm2.bStopClick(Sender: TObject);
begin
  if IdTCPServer1.Active then
  begin
    IdTCPServer1.Active := False;
    Log('Server stopped');
    bStop.Enabled := False;
    bStart.Enabled := True;
  end;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  bStart.Enabled := True;
  bStop.Enabled := False;
end;

procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var
  s: string;   FS:TFileStream;
begin

  if s ='1' then
  begin
    FS := TFileStream.Create(MyPath, fmOpenShare);
    try
      AContext.Connection.WriteStream(FS);
    finally
      FS.Free;
    end;
  end;

end;

procedure TForm2.Log(const s: string);
begin
  mLog.Lines.Add(s);
end

客户:

procedure TForm1.bConnectClick(Sender: TObject);
begin
  IdTCPClient1.Host := eServer.Text;
  IdTCPClient1.Port := StrToInt(ePort.Text);
  IdTCPClient1.Connect;

  if IdTCPClient1.Connected then
  begin
    Log('Connected to ' + IdTCPClient1.Host + ':' +
      IntToStr(IdTCPClient1.Port));
    bConnect.Enabled := False;
    bDisconnect.Enabled := True;
    bSend.Enabled := True;
  end;
end;

procedure TForm1.bDisconnectClick(Sender: TObject);
begin
  IdTCPClient1.Disconnect;
  bDisconnect.Enabled := False;
  bConnect.Enabled := True;
  bSend.Enabled := False;
end;

procedure TForm1.bSendClick(Sender: TObject);
var
  FS: TFileStream;
begin
//  IdTCPClient1.IOHandler.WriteLn(eTextToSend.Text);

  FS := TFileStream.Create('C:\Users\xxx\Desktop\test.txt', fmCreate);
  try
    IdTCPClient1.ReadStream(FS);
  finally
    Fs.Free;
  end;


end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  bDisconnect.Enabled := False;
  bSend.Enabled := False;
end;

procedure TForm1.Log(const s: string);
begin
  mLog.Lines.Add(s);
end;

1 个答案:

答案 0 :(得分:1)

您的客户端没有向服务器发送任何命令,并且服务器在发送文件之前没有等待任何命令。

但是,除此之外,您的代码无论如何都无法编译,因为TIdTCPConnection没有WriteStream()ReadStream()方法。正确的方法是TIdIOHandler.Write(TStream)TIdIOHandler.ReadStream()

但即便如此,您编写流和读取流的调用也不匹配,因为Write(TStream)默认情况下不会将流大小发送给对等方,但ReadStream()确实希望接收流默认大小。

尝试更像这样的东西:

服务器:

procedure TForm2.IdTCPServer1Execute(AContext: TIdContext);
var
  s: string;
  FS: TFileStream;
begin
  s := AContext.Connection.IOHandler.ReadLn;
  if s = 'SENDFILE' then
  begin
    try
      FS := TFileStream.Create(MyPath, fmOpenRead or fmShareDenyWrite);
    except
      AContext.Connection.IOHandler.WriteLn('500 Cannot open file');
      Exit;
    end;
    try
      AContext.Connection.IOHandler.WriteLn('200 Sending file');
      AContext.Connection.IOHandler.LargeStream := True;
      AContext.Connection.IOHandler.Write(FS, 0, True);
    finally
      FS.Free;
    end;
  end
  else    
    AContext.Connection.IOHandler.WriteLn('500 Unknown command');
end;

客户:

procedure TForm1.bSendClick(Sender: TObject);
var
  FS: TFileStream;
begin
  FS := TFileStream.Create('C:\Users\xxx\Desktop\test.txt', fmCreate);
  try
    try
      IdTCPClient1.IOHandler.SendCmd('SENDFILE', 200);
      IdTCPClient1.IOHandler.LargeStream := True;
      IdTCPClient1.IOHandler.ReadStream(FS, -1, False);
    finally
      FS.Free;
    end;
  except
    DeleteFile('C:\Users\xxx\Desktop\test.txt');
    raise;
  end;
end;

在这种情况下,您可以考虑使用TIdCmdTCPServer代替,然后您可以使用其CommandHandlers集合在设计时直观地定义命令,并指定OnCommand个事件处理程序来处理它们在运行时,例如:

// OnCommand handler for 'SENDFILE' command
procedure TForm2.IdCmdTCPServer1SENDFILECommand(ASender: TIdCommand);
var
  FS: TFileStream;
begin
  try
    FS := TFileStream.Create(MyPath, fmOpenRead or fmShareDenyWrite);
  except
    ASender.SetReply(500, 'Cannot open file');
    Exit;
  end;
  try
    ASender.SetReply(200, 'Sending file');
    ASender.SendReply;
    AContext.Connection.IOHandler.LargeStream := True;
    AContext.Connection.IOHandler.Write(FS, 0, True);
  finally
    FS.Free;
  end;
end;