- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想做的就是使用 TSockets 发送一个流,但遇到“内存不足”错误。我成功发送了文件,但没有发送图像。在服务器表单的 OnCreate
事件中,我正在创建流。对于客户端,在表单的 OnCreate
中,我正在创建流,也是一个 bmp。
我试图看看它是否没有发送,但它正在发送一些东西,只是我不知道是什么。在服务器端,我测试了向客户端发送命令,并且我知道它们发送了,我也使用 bool 值进行了测试,但仍然出现内存错误。
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
BytesReceived: Longint;
CopyBuffer: Pointer;
ChunkSize: Integer;
TempSize: Integer;
FSize: Integer;
writing: Boolean;
bmp: tbitmap;
const
MaxChunkSize: Longint = 8192;
begin
If FSize = 0 then
begin
If Socket.ReceiveLength > SizeOf(TempSize) then
begin
Socket.ReceiveBuf(TempSize, SizeOf(TempSize));
stream.SetSize(TempSize);
FSize := TempSize;
End;
End;
If (FSize > 0) and (writing) then //receiving the image
begin
GetMem(CopyBuffer, MaxChunkSize);
writing := true;
While Socket.ReceiveLength > 0 do
Begin
ChunkSize := Socket.ReceiveLength;
If ChunkSize > MaxChunkSize then
ChunkSize := MaxChunkSize;
BytesReceived := Socket.ReceiveBuf(CopyBuffer^, ChunkSize);
stream.Write(CopyBuffer^, BytesReceived);
Dec(FSize, BytesReceived);
End;
If FSize = 0 then
begin
bmp.LoadFromStream(stream);
self.Image1.Picture.Bitmap.LoadFromStream(stream);
stream.SetSize(0);
FSize := 0;
End;
FreeMem(CopyBuffer, MaxChunkSize);
writing := false;
stream.Free;
exit;
End;
end;
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
size: Integer;
Data: string;
begin
try
CaptureImage(bmp); //i have a procedure for this & know it works
bmp.SaveToStream(stream);
size := stream.size; //sending the tbitmap image
stream.Position := 0;
Socket.SendBuf(size, sizeof(size));
Socket.SendStream(stream);
except
stream.Free;
end;
最佳答案
从客户端读取数据时,您没有考虑FSize
。您正在读取客户端发送的内容,并且在达到流大小时不会停止。并且您没有考虑到它可能(并且可能会)需要多个 OnRead
事件来接收整个图像,因此您最终可能会过早地释放您的stream
。
此外,TCustomWinSocket.SendStream()
也不是很稳定,特别是在非阻塞模式下使用套接字时。您应该直接在循环中使用 TCustomWinSocket.SendBuf()
并根据需要处理任何套接字错误。
尝试更多类似这样的事情:
uses
..., System.Math;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
Socket.Data := nil;
end;
procedure TForm1.ServerSocket1ClientDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
if Socket.Data <> nil then
TMemoryStream(Socket.Data).Free;
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
Stream: TMemoryStream;
BytesReceived: Integer;
StreamSize, TempSize: Int32;
BytesRemaining: Int64;
P: PByte;
ChunkSize: Integer;
bmp: TBitmap;
const
MaxChunkSize: Int64 = 8192;
begin
Stream := TMemoryStream(Socket.Data);
// receiving the image size
if Stream = nil then
begin
if Socket.ReceiveLength < SizeOf(TempSize) then Exit;
BytesReceived := Socket.ReceiveBuf(TempSize, SizeOf(TempSize));
if BytesReceived <= 0 then Exit;
StreamSize := ntohl(TempSize);
Stream := TMemoryStream.Create;
Socket.Data := Stream;
Stream.Size := StreamSize;
BytesRemaining := StreamSize;
end else
BytesRemaining := Stream.Size - Stream.Position;
// receiving the image
if BytesRemaining > 0 then
begin
P := PByte(Stream.Memory);
if Stream.Position > 0 then
Inc(P, Stream.Position);
repeat
ChunkSize := Integer(Math.Min(BytesRemaining, MaxChunkSize));
BytesReceived := Socket.ReceiveBuf(P^, ChunkSize);
if BytesReceived <= 0 then Exit;
Inc(P, BytesReceived);
Dec(BytesRemaining, BytesReceived);
Stream.Seek(soCurrent, BytesReceived);
until BytesRemaining = 0;
end;
// loading the image
try
bmp := TBitmap.Create;
try
Stream.Position := 0;
bmp.LoadFromStream(Stream);
Image1.Picture.Bitmap.Assign(bmp);
finally
bmp.Free;
end;
finally
Socket.Data := nil;
Stream.Free;
end;
end;
uses
..., System.Math, Winapi.WinSock;
function SendRaw(Sckt: TSocket; const Data; Size: Integer);
var
P: PByte;
BytesSent: Integer;
begin
Result := 0;
P := PByte(@Data);
while Size > 0 do
begin
BytesSent := send(Sckt, P^, Size, 0);
if BytesSent = -1 then Exit;
Inc(P, BytesSent);
Dec(Size, BytesSent);
Inc(Result, BytesSent);
end;
end;
procedure WriteToSocket(Socket: TCustomWinSocket; const Data; Size: Integer);
var
Stream: TMemoryStream;
P: PByte;
BytesSent: Integer;
begin
if Size <= 0 then Exit;
Stream := TMemoryStream(Socket.Data);
P := PByte(@Data);
if not ((Stream <> nil) and (Stream.Size > 0)) then
begin
BytesSent := SendRaw(Socket.SocketHandle, P^, Size);
if BytesSent > 0 then
begin
Dec(Size, BytesSent);
if Size = 0 then Exit;
Inc(P, BytesSent);
end;
end;
if Stream = nil then
begin
Stream := TMemoryStream.Create;
Socket.Data := Stream;
end else
Stream.Seek(soEnd, 0);
Stream.WriteBuffer(P^, Size);
end;
procedure TForm1.ClientSocket1Connect(Sender: TObject; Socket: TCustomWinSocket);
begin
Socket.Data := nil;
end;
procedure TForm1.ClientSocket1Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
if Socket.Data <> nil then
TMemoryStream(Socket.Data).Free;
end;
procedure TForm1.ClientSocket1Write(Sender: TObject; Socket: TCustomWinSocket);
var
Stream: TMemoryStream;
BytesRemaining: Int64;
ChunkSize: Integer;
P: PByte;
begin
Stream := TMemoryStream(Socket.Data);
if Stream = nil then Exit;
BytesRemaining := Stream.Size;
if BytesRemaining = 0 then Exit;
P := PByte(Stream.Memory);
repeat
ChunkSize := Integer(Math.Min(BytesRemaining, MaxInt));
BytesSent := SendRaw(Socket.SocketHandle, P^, ChunkSize);
if BytesSent > 0 then
begin
Inc(P, BytesSent);
Dec(BytesRemaining, BytesSent);
end;
until (BytesSent < ChunkSize) or (BytesRemaining = 0);
if BytesRemaining = 0 then
Stream.Clear
else if P > Stream.Memory then
begin
MoveMemory(Stream.Memory, P, BytesRemaining);
Stream.Size := BytesRemaining;
end;
end;
procedure TForm1.ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
var
Stream: TMemoryStream;
bmp: TBitmap;
StreamSize, TempSize: Int32;
begin
...
Stream := TMemoryStream.Create;
try
// saving the bitmap image
bmp := TBitmap.Create;
try
CaptureImage(bmp);
bmp.SaveToStream(Stream);
finally
bmp.Free;
end;
// sending the TBitmap image
StreamSize := Stream.Size;
TempSize := htonl(StreamSize);
WriteToSocket(Socket, TempSize, sizeof(TempSize));
WriteToSocket(Socket, Stream.Memory^, StreamSize);
finally
Stream.Free;
end;
end;
关于delphi - TmemoryStream 服务器接收流时内存不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54187321/
我在这里阅读了很多关于将字符串写入 TMemoryStream 并保存到文件并将字符串读回 TMemoryStream 的讨论 我不知道我在这里做错了什么,但我的 SaveData 或 LoadDat
我尝试将加载到Memorystream中的前16个字节读取为TBytes。此ReadBuffer methot引发访问冲突异常。 我想从文件中加载加密的数据。前16个字节是用于创建文件的密码的MD5哈
我想做的就是使用 TSockets 发送一个流,但遇到“内存不足”错误。我成功发送了文件,但没有发送图像。在服务器表单的 OnCreate 事件中,我正在创建流。对于客户端,在表单的 OnCreate
如何将 TMemoryStream 的内容转换为变体?我使用Delphi 2010。 TMemoryStream存储文件的内容,可以是PDF或JPG(扫描文档)。 文件保存在 MS SQL 库中。当我
我正在使用 D6 Professional,需要从内存中已有的大量小字符串创建特定格式的文本文件。出于性能考虑,我正在考虑使用 TMemoryStream 来整理文件数据,然后通过 TFileStre
我正在delphi(RAD Studio)创建一个项目。数据库表中的某些行存储有图像。我想在运行时提取图像(为此我使用 TMemoryStream 数组)并在 frxReport 中显示它们。 我的代
这是我关于 SO 的第二个问题,我希望我的格式正确。 我在工作中发现 TFileStream 比 TMemoryStream 慢,我真的不知道为什么会这样。因此我决定做一些测试。 在我发现这种行为的应
以下函数采用 Richedit 中的选定文本控制,写入 TMemoryStream在回调函数内,然后以纯文本字符串形式返回原始 rtf 代码。 var MS: TMemoryStream; //
我有一些 Delphi 代码需要转换为 Qt/C++。 整体代码读取二进制数据文件,并提取部分数据。 Delphi代码读取文件内容如下: var m1 tmemorystream; h1
我正在尝试将 TMemoryStream 缓冲区的内容复制到 void 指针,下面您可以看到不起作用的示例代码 - void 缓冲区为空,但文本框包含有效大小 - 我用 winrar 大小检查了它。以
我正在尝试使用这样的简单代码行读取 bool 值:ReadBuffer(Result, 1)。 阅读后,结果为真。然而 Result:= not Result 不会“切换”值 false。 我在这里显
如何使用 TComInterface 对象并将其读入 TMemoryStream?我可以采用 TComInterface 并将其用作 TStream* 以某种方式使用 TMemoryStream Lo
如何通过datasnap与TMemoryStream传输TObject? TMyObject = class(TBizObject) FText: TMemoryStream; bytes t
我正在编写并行代码来枚举大量 CSV 文件,每个文件都包含历史股票数据(超过 6500 个代码),并计算每只股票是否已达到历史最高点。 我已经实现了一个线程池和 TThread 后代类,以在线程之间平
我在 XE2 中找到了 Remy Lebeau 的 IdTCP 组件的聊天演示,我想玩一下。 (可以找到 here )我想使用这些组件发送图片,最好的方法似乎是使用 TMemoryStream。如果我
我需要对 TTreeView 的树的 Unicode 字符串做一些事情,所以我想将此字符串加载到内存流中,然后将内存流加载到 TreeView 中。我怎样才能做到这一点? 最佳答案 您很想直接使用 T
在 Delphi 2009 之前我们有以下代码: function MemoryStreamToString(M : TMemoryStream): String; var NewCapaci
我有一个方法可以读取TStringGrid行的单元格中的数据,并将其复制到剪贴板。我有一个相应的方法将剪贴板中的数据粘贴到 TStringGrid 中的空行中。 这些方法是为 D7 编写的,但在迁移到
使用 Delphi Tokyo 10.2.3 并针对 Android,我正在创建多个线程来下载 PNG 图像并在后台对其进行解码。 由于这里解释的稳定性原因,使用 TBitmap 不是一个选项: Ge
我找到了遗留源代码和这里的摘录 - TMemoryStream *DFile = new TMemoryStream; TFileStream*BFile = new TFileStream; 以下是
我是一名优秀的程序员,十分优秀!