* * *

Author Topic: Error: Send buffer full, try again later  (Read 521 times)

reltek

  • Sr. Member
  • ****
  • Posts: 277
  • Programming is FUN only when it works :)
    • Cool Technology
Error: Send buffer full, try again later
« on: April 14, 2017, 05:26:24 pm »
Hello, I wrote a min program that is suppose to send files, but it is telling me, "Error: Send buffer full, try again later." I am not sure why. Here is the code that sends file.

Code: Pascal  [Select]
  1. const
  2.   BufferSize = 1024;
  3. var
  4.   Fs: TFileStream;
  5.   TotalCount: Integer;
  6.   Buffer: Pointer;
  7.   BytesToRead: Integer;  
  8. begin
  9.   Fs := TFileStream.Create('pathtoyourfile', fmOpenRead or fmshareDenyWrite);
  10.   try
  11.     TotalCount := 0;
  12.     GetMem(Buffer, BufferSize);
  13.     repeat
  14.       if TotalCount + BufferSize > Fs.Size then
  15.         BytesToRead := FS.Size - TotalCount
  16.       else
  17.         BytesToRead := BufferSize;
  18.       Fs.Read(Buffer^, BytesToRead);
  19.       aSocket.Send(Buffer, BufferSize);
  20.       TotalCount := TotalCount + BytesToRead;
  21.     until TotalCount >= FS.Size;
  22.     FreeMem(Buffer);
  23.   finally
  24.     Fs.Free;
  25.   end;                  
  26. end;

Any hints or help will be greatly appreciated.
« Last Edit: April 14, 2017, 05:51:36 pm by reltek »

wp

  • Hero Member
  • *****
  • Posts: 3335
Re: Error: Send buffer full, try again later
« Reply #1 on: April 14, 2017, 05:43:49 pm »
Nobody can help you if you don't tell us what FCon is.
Lazarus trunk / fpc 3.0.0 / Win32

reltek

  • Sr. Member
  • ****
  • Posts: 277
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Error: Send buffer full, try again later
« Reply #2 on: April 14, 2017, 05:52:27 pm »
Sorry....
FCon is actually the socket. I corrected the code above.

howardpc

  • Hero Member
  • *****
  • Posts: 2091
Re: Error: Send buffer full, try again later
« Reply #3 on: April 14, 2017, 06:14:14 pm »
Does it help if you change the repeat until condition to this?
Code: Pascal  [Select]
  1. until (TotalCount >= FS.Size) or (BytesToRead < BufferSize);

reltek

  • Sr. Member
  • ****
  • Posts: 277
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Error: Send buffer full, try again later
« Reply #4 on: April 17, 2017, 04:07:26 pm »
I am still getting the same error - Error: Send Buffer full try again later - by the server or the host.

GetMem

  • Hero Member
  • *****
  • Posts: 1990
Re: Error: Send buffer full, try again later
« Reply #5 on: April 17, 2017, 04:58:49 pm »
What is your platform? Lazarus/FPC version? What component? LNet, Indy, Syanpse? It looks like you copied this code:
http://forum.lazarus.freepascal.org/index.php/topic,35272.msg233478.html#msg233478
which was a hypothetical example, I don't think will work in real life, however you can find working code below, if lnet is what are you after: http://forum.lazarus.freepascal.org/index.php/topic,35272.msg233630.html#msg233630

Remy Lebeau

  • Full Member
  • ***
  • Posts: 210
    • Lebeau Software
Re: Error: Send buffer full, try again later
« Reply #6 on: April 17, 2017, 06:35:14 pm »
Code: Pascal  [Select]
  1. aSocket.Send(Buffer, BufferSize);

Using BufferSize when calling Send() is wrong.  You need to use BytesToRead instead.  Actually, you should be using the return value of TFileStream.Read() instead, eg:

Code: [Select]
const
  BufferSize = 1024;
var
  Fs: TFileStream;
  Buffer: Pointer;
  BytesRead: Integer; 
begin
  Fs := TFileStream.Create('pathtoyourfile', fmOpenRead or fmshareDenyWrite);
  try
    GetMem(Buffer, BufferSize);
    try
      repeat
        BytesRead := Fs.Read(Buffer^, BufferSize);
        if BytesRead <= 0 then Break;
        aSocket.Send(Buffer, BytesRead);
      until False;
    finally
      FreeMem(Buffer);
    end;
  finally
    Fs.Free;
  end;                 
end;
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) open source project - Admin, Developer

reltek

  • Sr. Member
  • ****
  • Posts: 277
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Error: Send buffer full, try again later
« Reply #7 on: April 19, 2017, 05:06:56 pm »
Code: Pascal  [Select]
  1. aSocket.Send(Buffer, BufferSize);

Using BufferSize when calling Send() is wrong.  You need to use BytesToRead instead.  Actually, you should be using the return value of TFileStream.Read() instead, eg:

Code: [Select]
const
  BufferSize = 1024;
var
  Fs: TFileStream;
  Buffer: Pointer;
  BytesRead: Integer; 
begin
  Fs := TFileStream.Create('pathtoyourfile', fmOpenRead or fmshareDenyWrite);
  try
    GetMem(Buffer, BufferSize);
    try
      repeat
        BytesRead := Fs.Read(Buffer^, BufferSize);
        if BytesRead <= 0 then Break;
        aSocket.Send(Buffer, BytesRead);
      until False;
    finally
      FreeMem(Buffer);
    end;
  finally
    Fs.Free;
  end;                 
end;

Hi Remy. Thank you for that awesome sample code. I was wondering if you could also show me how you would do the receiving of the file. I just want to make sure I am doing it right. Thank you.

Here is my code:

Code: Pascal  [Select]
  1. const
  2. BufferSize = 1024;
  3. var
  4.   Fs: TFileStream;
  5.   Buffer: Pointer;
  6.   ReadBytes:Integer;
  7.   Fnet : TLConnection;
  8. begin
  9.  
  10. fs := TFileStream.Create('local file name', fmCreate);
  11.  
  12.   try
  13.    GetMem(Buffer, BufferSize);
  14.    
  15.    while True do
  16.    begin
  17.        ReadBytes := fNet.Get(Buffer, BufferSize);
  18.        
  19.        if (ReadBytes = 0) then
  20.             break
  21.        else
  22.             fs.write(Buffer, ReadBytes);
  23.        
  24.        Application.ProcessMessages;
  25.        Sleep(1);
  26.    end;
  27.   Finally
  28.    fs.free;
  29.    freemem(Buffer);
  30.   end;
  31. end;
  32.  

Remy Lebeau

  • Full Member
  • ***
  • Posts: 210
    • Lebeau Software
Re: Error: Send buffer full, try again later
« Reply #8 on: April 19, 2017, 07:58:20 pm »
I was wondering if you could also show me how you would do the receiving of the file. I just want to make sure I am doing it right.

The sender needs to indicate when the file is finished so the receiver knows when to stop reading.  There are only two ways to do that reliably - close the connection at the end of the file, or else send the file size before sending the file data.  Your current code expects the first, but the second is preferred instead, eg:

Code: [Select]
procedure sendRaw(Fnet: TLConnection; var Buffer; BufferSize: Integer);
var
  Ptr: PByte;
  NumSent: Integer;
begin
  Ptr := PByte(@Buffer);
  while BufferSize > 0 do
  begin
    NumSent := Fnet.Send(Ptr, BufferSize);
    if NumSent <= 0 then raise Exception.Create('socket send error');
    Inc(Ptr, NumSent);
    Dec(BufferSize, NumSent);
  end;
end;

...

const
  BufferSize = 1024;
var
  Fs: TFileStream;
  FileSize, FileSizeTmp: Int64;
  Buffer: Pointer;
  BytesRead: Integer; 
  Fnet: TLConnection;
begin
  Fnet := ...;
  Fs := TFileStream.Create('pathtoyourfile', fmOpenRead or fmshareDenyWrite);
  try
    FileSize := Fs.Size;

    // you may have to find a 3rd party implementation
    // of htonll(), or implement it manually...
    FileSizeTmp = htonll(FileSizeTmp);
    sendRaw(Fnet, FileSizeTmp, sizeof(FileSizeTmp));

    if FileSize > 0 then
    begin
      GetMem(Buffer, BufferSize);
      try
        repeat
          if FileSize > BufferSize then
            BytesRead := BufferSize
          else
            BytesRead := Integer(FileSize);
          BytesRead := Fs.Read(Buffer^, BytesRead);
          if BytesRead <= 0 then raise Exception.Create('file read error');
          sendRaw(Fnet, Buffer, BytesRead);
          Dec(FileSize, BytesRead);
        until FileSize = 0;
      finally
        FreeMem(Buffer);
      end;
    end;
  finally
    Fs.Free;
  end;                 
end;

Code: [Select]
procedure readRaw(Fnet: TLConnection; var Buffer; BufferSize: Integer);
var
  Ptr: PByte;
  NumRead: Integer;
begin
  Ptr := PByte(@Buffer);
  while BufferSize > 0 do
  begin
    NumRead := Fnet.Get(Ptr, BufferSize);
    if NumRead <= 0 then raise Exception.Create('socket read error');
    Inc(Ptr, NumRead);
    Dec(BufferSize, NumRead);
  end;
end;

...

const
  BufferSize = 1024;
var
  Fs: TFileStream;
  FileSize: Int64;
  Buffer: Pointer;
  ReadBytes: Integer;
  Fnet: TLConnection;
begin
  Fnet := ...;
  Fs := TFileStream.Create('local file name', fmCreate);
  try
    readRaw(Fnet, FileSize, sizeof(FileSize));

    // you may have to find a 3rd party implementation
    // of ntohll(), or implement it manually...
    FileSize := ntohll(FileSize);

    if FileSize > 0 then
    begin
      GetMem(Buffer, BufferSize);
      try
        repeat
          if FileSize > BufferSize then
            ReadBytes := BufferSize
          else
            ReadBytes := Integer(FileSize);
          readRaw(Fnet, Buffer, ReadBytes);
          Fs.WriteBuffer(Buffer^, ReadBytes);
          Dec(FileSize, ReadBytes);
        until FileSize = 0;
      finally
        FreeMem(Buffer);
      end;
    end;
  finally
    Fs.free;
  end;
end;
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) open source project - Admin, Developer

reltek

  • Sr. Member
  • ****
  • Posts: 277
  • Programming is FUN only when it works :)
    • Cool Technology
Re: Error: Send buffer full, try again later
« Reply #9 on: April 19, 2017, 10:38:18 pm »
 :)
Thank you so much, Remi.

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus