[英]Send files using sockets in Delphi 2010
嗨,我正在通過tsocket發送文件,我正在編輯第一個代碼以不使用opendilalog,但我想使用一個字符串來發送文件的路徑,問題是OpenDialog編輯的第二個代碼未使用向我射擊錯誤,指出要發送的文件正在被另一個進程使用。
第一個來源
procedure TForm1.Button2Click(Sender: TObject);
begin
if ClientSocket1.Active = True then
begin
OpenDialog1.Filter := 'All Files (*.*)'; // you can add more choices by adding | and followed by description and (*.extension)
OpenDialog1.FilterIndex := 1; // Here you follow which index number from above you want
if OpenDialog1.Execute then
begin
Edit1.Text := ExtractFileName(OpenDialog1.FileName); // To send as filename after
ClientSocket1.Socket.SendText('FILE!'+Edit1.Text);
sleep(2000); // Need to sleep so the other end has time to process the commands
Streamsize := TFileStream.Create(OpenDialog1.FileName, fmopenread); // Stream created just to Calculate size
Edit2.Text := inttostr(Streamsize.Size);
Sleep(2000);
ClientSocket1.Socket.SendText('SIZE!'+Edit2.Text); // Sends filesize through primary socket
Streamsize.Position := 0;
Streamsize.Free;
sleep(2000);
ClientSocket2.Address := Edit3.Text;
ClientSocket2.Open; // ready to send file on second socket
if ClientSocket2.Socket.SendStream(TFileStream.Create(OpenDialog1.FileName, fmopenRead)) then memo1.Lines.Add('File Sent');
// above creates a stream and sends as a stream its in a if line because this is the only way it will automatically check the byte order and send the whole stream
end;
end
else
MessageDlg('Error: You are not connected', mtError, [MbOK],0); // Error Check above code won't work until the socket is connected
end;
第二個來源
procedure TForm1.Button2Click(Sender: TObject);
var
archivo: string;
begin
archivo := 'c:/clap.jpg';
if ClientSocket1.Active = True then
begin
Edit1.Text := ExtractFileName(archivo);
// To send as filename after
ClientSocket1.Socket.SendText('FILE!' + Edit1.Text);
sleep(2000); // Need to sleep so the other end has time to process the commands
Streamsize := TFileStream.Create(archivo, fmopenread);
// Stream created just to Calculate size
Edit2.Text := inttostr(Streamsize.Size);
sleep(2000);
ClientSocket1.Socket.SendText('SIZE!' + Edit2.Text);
// Sends filesize through primary socket
Streamsize.Position := 0;
Streamsize.Free;
sleep(2000);
ClientSocket2.Address := '127.0.0.1';
ClientSocket2.Open; // ready to send file on second socket
if ClientSocket2.Socket.SendStream(TFileStream.Create(archivo, fmopenread))
then
Memo1.Lines.Add('File Sent');
// above creates a stream and sends as a stream its in a if line because this is the only way it will automatically check the byte order and send the whole stream
end
else
MessageDlg('Error: You are not connected', mtError, [MbOK], 0); // Error Check above code won't work until the socket is connected
end;
服務器。
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ScktComp, ComCtrls, idglobal, ExtCtrls, ShellAPI;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Label1: TLabel;
ServerSocket1: TServerSocket;
ServerSocket2: TServerSocket;
GroupBox1: TGroupBox;
Edit1: TEdit;
Edit2: TEdit;
Label2: TLabel;
Label3: TLabel;
ProgressBar1: TProgressBar;
Timer1: TTimer;
StatusBar1: TStatusBar;
procedure Button1Click(Sender: TObject);
procedure ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket2Accept(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure ServerSocket2ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
procedure FormCreate(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
IncommingStream: TFileStream;
TimeTaken: integer;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// Written by me ColdFuzion
// All i ask is i be given some credit for coding this my e-mail is ColdFuzion@hushmail.com
// Program Usage: To recieve Files sent by the client
procedure TForm1.Button1Click(Sender: TObject);
begin
ServerSocket1.Open;
Memo1.Lines.Add('Server Listening on '+inttostr(ServerSocket1.Port) );
end;
procedure TForm1.ServerSocket1Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add('Client connected From '+Socket.RemoteHost)
// Adds the clients host as it connects
end;
procedure TForm1.ServerSocket2Accept(Sender: TObject;
Socket: TCustomWinSocket);
begin
Memo1.Lines.Add('Incoming File Transfer');
end;
procedure TForm1.ServerSocket1ClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var IncommingText, StrippedData, CommandName: string;
begin
IncommingText := socket.ReceiveText;
StrippedData := copy(IncommingText,6,length(IncommingText) );
CommandName := copy(IncommingText,0,5);
if CommandName = 'FILE!' then
begin
IncommingStream := TFileStream.Create(StrippedData, fmCREATE or fmOPENWRITE and fmsharedenywrite); // Once File name is recieved the stream to recieve
Edit1.Text := StrippedData; // The file is created
ServerSocket2.Open;
end
else
if CommandName = 'SIZE!' then
begin
Edit2.Text := StrippedData;
ProgressBar1.Max := StrToInt(StrippedData);
ProgressBar1.Min := 0;
Memo1.lines.Add('Recieving File '+Edit1.Text +' of size '+Edit2.Text);
end;
end;
procedure TForm1.ServerSocket2ClientRead(Sender: TObject;
// This is the secondary socket it is the most important part of the program
Socket: TCustomWinSocket);
// It processes the incomming file stream
var Buffer: array [0..9999] of Char;
IncommingLen, RecievedLen: integer;
Filepath: string;
begin
Timer1.Enabled := True;
IncommingLen := socket.ReceiveLength;
// If the size of any incomming data is the size of 0 then the process begins
Filepath := ExtractFilePath(Edit1.Text)+Edit1.Text;
// Sets a String Filepath for the actual directory with the filename so that the shellexecute can run this after
while IncommingLen > 0 do
// Must make sure the process ends
begin
RecievedLen := socket.ReceiveBuf(Buffer, Sizeof(Buffer));
// Changes the size of RecievedLen by the amount of incoming data recieved
if RecievedLen <= 0 then
// Small part of the code where once the buffer reaches 0 the code will exit
Break
else
IncommingStream.Write(Buffer, RecievedLen);
// Writes the Incoming data into a new stream by the filename and size which is recieved
ProgressBar1.StepBy(RecievedLen);
// through the primary socket Also this line increases the progess indicator bar
if IncommingStream.Size >= strtoint(Edit2.Text) then
// Onces the stream size begins to reach the size which was sent before sending the file then this
begin
// procedure will start
IncommingStream.Free;
// Free's the stream
memo1.Lines.Add('File '+Edit1.Text +' Recieved Successfuly');
memo1.Lines.Add('Time Taken to Recieve File ' +IntToStr(TimeTaken)+' seconds');
ServerSocket1.Socket.Connections[0].SendText('DONE!');
Edit1.Text := '';
// From here it starts setting the variables back
Edit2.Text := '';
ProgressBar1.Position := 0;
Timer1.Enabled := False;
TimeTaken := 0;
if Messagedlg('Would you Like to open the recieved file?', mtConfirmation, [MbYes,MbNo],0) = MrYes then // Simply asks the user if he wants to open the file if yes will execute if no break
begin
ShellExecute(Form1.Handle, 'open', pchar(Filepath),nil, nil, SW_NORMAL); // A shellapi was added to uses to beable to execute this line
end;
Break; // This line basically executes any file using the extension from the windows ini files.
end;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Memo1.Text := '';
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
inc(TimeTaken,1);
// Counts number of seconds starts once the filestream begins
end;
end.
// This entire Program could use alot more Error checking but it simply is a very basic
// Example of how to do certain things using the basic components that come with Delphi
// There are hardly any examples of sending files with delphi on the internet so most of
// the code here had to be improvised i hope this helps people where i had to struggle with
我可以更正為第二個代碼以消除更多錯誤嗎?
如果操作系統抱怨該文件已在使用中,則說明它實際上已在使用中。
您正在創建到同一個文件的多個流(也使用了錯誤的路徑分隔符)。 創建一個流並重復使用多次,例如:
procedure TForm1.Button2Click(Sender: TObject);
var
archivo: string;
Strm: TFileStream;
begin
archivo := 'c:\clap.jpg';
if ClientSocket1.Active then
begin
Strm := TFileStream.Create(archivo, fmOpenRead or fmShareDenyWrite);
try
Edit1.Text := ExtractFileName(archivo);
Edit2.Text := IntToStr(Strm.Size);
ClientSocket1.Socket.SendText('FILE!' + Edit1.Text);
// Need to sleep so the other end has time to process the commands
Sleep(2000);
ClientSocket1.Socket.SendText('SIZE!' + Edit2.Text);
Sleep(2000);
ClientSocket2.Address := '127.0.0.1';
ClientSocket2.Open; // ready to send file on second socket
if ClientSocket2.Socket.SendStream(Strm) then
begin
// SendStream() takes ownership of the Stream, so don't free it!
Strm := nil;
Memo1.Lines.Add('File Sent');
end;
finally
Strm.Free;
end;
end
else
MessageDlg('Error: You are not connected', mtError, [MbOK], 0);
end;
如前所述,SendStream()獲得流的所有權。 如果您在非阻塞模式下使用套接字,則可能需要花費一些時間來傳輸整個流。 在傳輸完成之前,您將無法再次重新打開文件。 那可以解釋您所看到的錯誤。
如此說來,您必須在協議中引入休眠機制以正確處理命令這一事實意味着您在開始時就沒有很好地設計協議。 在命令之間放置定界符會更加可靠,例如:
procedure TForm1.Button2Click(Sender: TObject);
var
archivo: string;
Strm: TFileStream;
begin
archivo := 'c:\clap.jpg';
if ClientSocket1.Active then
begin
Strm := TFileStream.Create(archivo, fmOpenRead or fmShareDenyWrite);
try
Edit1.Text := ExtractFileName(archivo);
Edit2.Text := IntToStr(Strm.Size);
ClientSocket1.Socket.SendText('FILE!' + Edit1.Text + #13#10);
ClientSocket1.Socket.SendText('SIZE!' + Edit2.Text + #13#10);
ClientSocket2.Address := '127.0.0.1';
ClientSocket2.Open; // ready to send file on second socket
if ClientSocket2.Socket.SendStream(Strm) then
begin
// SendStream() takes ownership of the Stream and will free it
// after it is done sending, so don't free it yourself!
Strm := nil;
Memo1.Lines.Add('File Sent');
end;
finally
Strm.Free;
end;
end
else
MessageDlg('Error: You are not connected', mtError, [MbOK], 0);
end;
然后,接收器可以簡單地讀取入站數據,並根據需要在定界符上對其進行拆分,而無需進行睡眠。
順便說一句,您實際上是在使用不同的語法重新創建FTP協議 ,所以為什么不使用實際的FTP協議呢? 有許多FTP組件/庫可供使用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.