Hi I'm studying sockets on how to send and receive files, I'm using the component ServerSocket1 to do this I have the following code I found searching google. the client
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
ClientSocket1: TClientSocket;
OpenDialog1: TOpenDialog;
procedure Button1Click(Sender: TObject);
procedure ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ClientSocket1Error(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure Button2Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure ClientSocket1Read(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
Stream: TMemoryStream;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientSocket1.Address:= '127.0.0.1';
ClientSocket1.Port:= 2500;
ClientSocket1.Open;
end;
procedure TForm1.ClientSocket1Connect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage('Connected.. Now go load a file!');
end;
procedure TForm1.ClientSocket1Error(Sender: TObject;
Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;
var ErrorCode: Integer);
begin
ShowMessage('Did you startup the server? I cannot find it!');
end;
procedure TForm1.Button2Click(Sender: TObject);
var
Size: Integer;
begin
if OpenDialog1.Execute Then
begin
Stream.LoadFromFile(OpenDialog1.Filename);
Size:= Stream.Size;
ClientSocket1.Socket.SendBuf(Size,SizeOf(Size));
ClientSocket1.Socket.SendStream(Stream);
End;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Stream:= TMemoryStream.Create;
end;
procedure TForm1.ClientSocket1Read(Sender: TObject;
Socket: TCustomWinSocket);
var
S: String;
begin
S:= Socket.ReceiveText;
Socket.Close;
ShowMessage('Client: '+S);
end;
end.
the server
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ScktComp;
type
TForm1 = class(TForm)
ServerSocket1: TServerSocket;
SaveDialog1: TSaveDialog;
procedure FormCreate(Sender: TObject);
procedure ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
private
{ Private declarations }
Stream: TMemoryStream;
FSize: Integer;
writing: Boolean;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
ServerSocket1.Port:= 2500;
ServerSocket1.Active:= True;
Stream:= TMemoryStream.Create;
writing:= False;
end;
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage('A client has connected');
end;
procedure TForm1.ServerSocket1Listen(Sender: TObject;
Socket: TCustomWinSocket);
begin
ShowMessage('I''m listening');
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
BytesReceived: Longint;
CopyBuffer: Pointer; { buffer for copying }
ChunkSize: Integer;
TempSize: Integer;
const
MaxChunkSize: Longint = 8192; { copy in 8K chunks }
begin
If FSize=0 then
begin
If Socket.ReceiveLength>SizeOf(TempSize) then
begin
Socket.ReceiveBuf(TempSize,SizeOf(TempSize));
Stream.SetSize(TempSize);
FSize:= TempSize //Threadsafe code!
End;
End;
If (FSize>0) and not(writing) then
begin
GetMem(CopyBuffer, MaxChunkSize); { allocate the buffer }
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); { ...write chunk }
Dec(FSize,BytesReceived);
End;
If FSize=0 then
If SaveDialog1.Execute then
begin
If FileExists(SaveDialog1.Filename) then
DeleteFile(SaveDialog1.Filename);
Stream.SaveToFile(SaveDialog1.Filename);
Socket.SendText('File received!');
Stream.SetSize(0);
FSize:= 0;
End;
FreeMem(CopyBuffer, MaxChunkSize); { allocate the buffer }
Writing:= False;
End;
end;
end.
The problem in this code that eh had is that I can only send one I can send a file because when I try to re-send other file errors throws me as 'Access violation at address' or 'Stream read error'.
that I can do to fix this code and you can send multiple files after each?
there is a reference of how to do it with indy sockets?
This is because memorystream used to open the file is not free. You have to free the stream variable before loading the next file to be sent.
I modified your code a bit and it is now working perfectly, I request various files and is ok.
the server
procedure TForm1.ServerClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var
BytesReceived: Longint;
CopyBuffer: Pointer; { buffer for copying }
ChunkSize: Integer;
TempSize: Integer;
FileName: array [0..255] of char;
const
MaxChunkSize: Longint = 8192; { copy in 8K chunks }
begin
If FSize=0 then
begin
If Socket.ReceiveLength>SizeOf(TempSize) then
begin
Socket.ReceiveBuf(TempSize,SizeOf(TempSize));
Socket.ReceiveBuf(FileName, sizeOf(FileName));
Save.FileName:= FileName; //I added
Stream:= TMemoryStream.Create;
Stream.SetSize(TempSize);
FSize:= TempSize; //Threadsafe code!
writing:= True;
End;
End;
If (FSize>0) and (writing) then
{before not(writing) -> because in big files, ServerClientRead is call more than one time and the transfer was stopped after the first call, but now it continues.}
begin
GetMem(CopyBuffer, MaxChunkSize); { allocate the buffer }
While Socket.ReceiveLength>0 do
Begin
ChunkSize:= Socket.ReceiveLength;
If ChunkSize > MaxChunkSize then ChunkSize:= MaxChunkSize;
BytesReceived:= Socket.ReceiveBuf(CopyBuffer^,ChunkSize);
Stream.Write(CopyBuffer^, BytesReceived); { ...write chunk }
Dec(FSize,BytesReceived);
End;
FreeMem(CopyBuffer, MaxChunkSize); { free allocated buffer, now here }
If FSize
Client button click:
procedure TForm1.Button1Click(Sender: TObject);
var ms: TMemoryStream;
size: Integer;
FileName: array [0..255] of char;
begin
if Open.Execute then
begin
ms:= TMemoryStream.Create;
try
ms.LoadFromFile(open.FileName);
ms.Position:= 0;
Size:= MS.Size;
Client.Socket.SendBuf(Size,SizeOf(Size));
StrPLCopy(FileName, ExtractFileName(Open.FileName), High(FileName));
Client.Socket.SendBuf(FileName, SizeOf(FileName));
client.Socket.SendStream(ms);
except
ms.Free;
end;
end;
end;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.