【发布时间】:2019-12-28 21:32:48
【问题描述】:
我尝试将 .jpg 文件从 ClientSocket 发送到 ServerSocket,但显然在 SendText 和 SendStream 函数周围遇到了麻烦,因为结果例如,执行 SendText 后获得的始终为 0。但是存在其他奇怪的事情,那就是当我在发送文件大小之前放置 ShowMessage() 时,SendText 有效(并且收到了大小)但 SendStream 失败-1 的结果。
如何解决?
这是我最后一次尝试>
发件人:
uses
System.Win.ScktComp, Vcl.Imaging.jpeg;
type
TForm1 = class(TForm)
ClientSocket1: TClientSocket;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
P: TPicture;
J: TJpegImage;
MS: TMemoryStream;
Sent: Boolean;
begin
ClientSocket1.Host := '192.168.0.10';
ClientSocket1.Port := 1234;
ClientSocket1.Active := True;
try
MS := TMemoryStream.Create;
MS.Position := 0;
P := TPicture.Create;
P.Bitmap.LoadFromFile('sent.bmp');
J := TJpegImage.Create;
J.Assign(P.Bitmap);
J.CompressionQuality := 100;
J.SaveToStream(MS);
ShowMessage(IntToStr(Round(MS.Size / 1024)));
ClientSocket1.Socket.SendText(IntToStr(MS.Size) + #0);
Sent := ClientSocket1.Socket.SendStream(MS);
ShowMessage(BoolToStr(Sent));
finally
MS.Free;
P.Free;
J.Free;
end;
end;
end.
接收者:
uses
System.Win.ScktComp, Vcl.Imaging.jpeg;
type
TForm1 = class(TForm)
Button1: TButton;
ServerSocket1: TServerSocket;
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
ServerSocket1.Port := 1234;
ServerSocket1.Active := True;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
s: string;
Stream: TMemoryStream;
Receiving: Boolean;
stSize: Integer;
jpg: TJpegImage;
begin
if Socket.ReceiveLength > 0 then
begin
s := Socket.ReceiveText;
if not Receiving then
begin
if Pos(#0, s) > 0 then
begin
stSize := strToInt(Copy(s, 1, Pos(#0, s) - 1));
ShowMessage(IntToStr(Round(stSize / 1024)));
end
else
;
Stream := TMemoryStream.Create;
Receiving := true;
Delete(s, 1, Pos(#0, s));
end;
try
Stream.Write(AnsiString(s)[1], length(s));
if Stream.Size = stSize then
begin
Stream.Position := 0;
Receiving := false;
jpg := TJpegImage.Create;
jpg.LoadFromStream(Stream);
jpg.SaveToFile('received.jpg');
Stream.Free;
end;
except
Stream.Free;
end;
end;
end;
end.
【问题讨论】:
-
建议:使用十多年未弃用的组件。
-
另请注意,您的 try..finally 设置方式存在内存泄漏风险。对象创建应该在
try之前,而不是之后。如果P.Bitmap.LoadFromFile('sent.bmp');失败会怎样?J永远不会被创建,但您仍然会尝试释放它。您也可以在没有任何图像组件的情况下完成所有这些操作。您只需要使用TFileStream而不是TMemoryStream。您还会在接收器中泄漏jpg。 -
@JerryDodge, "
you are risking memory leaks the way your try..finally is set up. Object creation should be before the try, not after it." 谢谢。 -
@JerryDodge 不是...对象变量应该在
try之前初始化,是的。不一定创建。在尝试之前创建它们有其自身的内存泄漏风险,除非您执行trycascade。 -
@KenBourassa,你是对的,我测试了 Jerry 的建议,也有内存泄漏。
标签: sockets delphi client-server sendfile delphi-10.3-rio