您好我通过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
我可以更正第二个代码来解决错误吗?
答案 0 :(得分:0)
如果操作系统抱怨该文件已被使用,那么它确实已经在使用中。
您正在为同一个文件创建多个流(您也使用了错误的路径分隔符)。创建一个流并重复使用多次,例如:
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 protocol,但是为什么不使用实际的FTP协议呢?有很多FTP组件/库可供使用。