现在想使用 TServerSocket stThreadBlocking模式做一个服务器,然后用 TClientSocket做一个客户端,
要求客户端发送一个数据包,内容为:AskFile 服务器接收到后组织数据包,内容为:SendFile, 后面加文件信息及文件,传送给客户端,请高手指教,初次写网络文面的,还望高手帮忙.
要求客户端发送一个数据包,内容为:AskFile 服务器接收到后组织数据包,内容为:SendFile, 后面加文件信息及文件,传送给客户端,请高手指教,初次写网络文面的,还望高手帮忙.
Classes, Windows, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
IdGlobal, SysUtils, StrUtils;type
ThreadGetFile = class(TThread)
procedure IdTcpClientGetWork(ASender: TObject; AWorkMode: TWorkMode;
AWorkCount: Integer);
private
{ Private declarations }
FSaveDir, FFileName : string;
FIpVer : TIdIPVersion;
IdTcpClientGet : TIdTCPClient;
FStreamSize : Int64;
FItemIndex : Integer;
protected
procedure Execute; override;
public
constructor Create(FileName , SaveDir : string; aIpVer : TIdIPVersion);
end;implementation
uses
Main;
{ ThreadGetFile }function GetPort(aStr : string) : Integer; stdcall;
begin
Result := StrToInt(Copy(aStr,Pos(':',aStr) + 1,Pos(')',aStr) - Pos(':',aStr) - 1));
end;
function GetHost(aStr : string) : string; stdcall;
begin
Result := Copy(aStr,Pos('(',aStr) + 1,Pos(':',aStr) - Pos('(',aStr) - 1);
end;
function GetDisplayName(aStr : string) : string; stdcall;
begin
Result := LeftBStr(aStr,Pos('(',aStr) - 1);
end;constructor ThreadGetFile.Create(FileName , SaveDir : string; aIpVer : TIdIPVersion);
begin
FFileName := FileName;
FItemIndex := -1;
IdTcpClientGet := TIdTCPClient.Create(nil);
IdTcpClientGet.OnWork := IdTcpClientGetWork;
FIpVer := aIpVer;
FSaveDir := SaveDir;
inherited Create(True);
end;procedure ThreadGetFile.IdTcpClientGetWork(ASender: TObject;
AWorkMode: TWorkMode; AWorkCount: Integer);
begin
//
if FItemIndex <> -1 then
FrmMain.Lst1.Items[FItemIndex] := '开始接收数据...' + FormatFloat('0',AWorkCount/FStreamSize*100) + '%';
end;procedure ThreadGetFile.Execute;
var
Size : Int64;
CurInfo, S : string;
FileStream : TFileStream; function ProDir (aDir : string) : string;
begin
if RightBStr(aDir,1) = '\' then
Result := aDir
else
Result := aDir + '\';
end;
begin
while CurItem < ComLst.Count do
begin
EnterCriticalSection(Lock); //进入临界区
CurInfo := ComLst[CurItem];
Inc(CurItem);
LeaveCriticalSection(Lock); //退出临界区
with IdTcpClientGet do
begin
try
Host := GetHost(CurInfo);
Port := GetPort(CurInfo);
IPVersion := FIpVer;
ReadTimeout := 10000;
ConnectTimeout := 10000;
OnWork := IdTcpClientGetWork;
Connect;
IOHandler.WriteLn('file');
s := IOHandler.ReadLn;
if s = '-filename' then
begin
IOHandler.WriteLn(FFileName);
s := IOHandler.ReadLn;
if s = 'file not found' then
begin
//文件不存在
FrmMain.Lst1.Items.Add(CurInfo + ' 文件不存在! ' + FFileName);
end
else
begin
s := RightBStr(s,Length(s) - Pos(':',s));
// s := GetDisplayName(FInfo) + s;
FileStream := TFileStream.Create(ProDir(FSaveDir) + GetDisplayName(CurInfo) + s,
fmCreate);
IOHandler.WriteLn('-size');
s := IOHandler.ReadLn;
Size := StrToInt64Def(s,-1);
if Size > -1 then
begin
FrmMain.Lst1.Items.Add(CurInfo + ' 获取文件大小: ' + IntToStr(Size) + ' Byte');
FStreamSize := Size;
IOHandler.WriteLn('-ready');
IOHandler.LargeStream := True;
FItemIndex := FrmMain.Lst1.Items.Add(CurInfo + ' 开始接收数据... ');
IOHandler.ReadStream(FileStream,Size);
FItemIndex := -1;
FileStream.Free;
IOHandler.WriteLn('-ok');
FrmMain.Lst1.Items.Add(CurInfo + ' 文件传输完成! ' + FFileName);
end;
end;
end;
Disconnect;
except
FrmMain.Lst1.Items.Add(CurInfo + ' 连接失败!');
end;
end;
end;
Dec(ThCount);
if ThCount = 0 then
begin
IdTcpClientGet.Free;
FrmMain.Lst1.Items.Add('------------任务完成!------------');
FrmMain.Lst1.Items.Add('');
end;
end;
var
SPort,sIP: string;
s: string;
FileName, SaveFileName: string;
FileStream: TFileStream;
begin
if AContext.Connection.Connected then
begin
sIP := AContext.Binding.PeerIP;
SPort := IntToStr(AContext.Binding.PeerPort);
s := AContext.Connection.IOHandler.ReadLn;
if SameText(s,'test connect') then
begin
//测试连接
AContext.Connection.IOHandler.WriteLn('ok');
AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Connect Test '
+ AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
end;
if SameText(S, 'file') then
begin
AContext.Connection.IOHandler.WriteLn('-filename');
S := AContext.Connection.IOHandler.ReadLn;
s := ReplaceStr(s,'%Cur%',ExtractFilePath(ParamStr(0))); //替换程序当前路径
// AddLog('test:'+s);
if FileExists(s) then
begin
//文件存在,发送文件名
// AddLog('True');
FileName := s;
SaveFileName := ExtractFileName(s);
AContext.Connection.IOHandler.WriteLn('filename:' + SaveFileName);
S := AContext.Connection.IOHandler.ReadLn;
if s = '-size' then
begin
// if ExtractFileName(FileName) = 'Run.log' then
// begin
// EnterCriticalSection(FUI);
// FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
// LeaveCriticalSection(FUI);
// end
// else
FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
AContext.Connection.IOHandler.WriteLn(IntToStr(FileStream.Size));
S := AContext.Connection.IOHandler.ReadLn;
if s='-ready' then
begin
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.Write(FileStream, FileStream.Size);
S := AContext.Connection.IOHandler.ReadLn;
if s='-ok' then
AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Send File: ' + FileName + ' Ok! '
+ AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort))
else
AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' Send File: ' + FileName + ' Error! '
+ AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
end;
FileStream.Free;
end;
end
else
begin
//文件不存在
// AddLog('false');
AContext.Connection.IOHandler.Writeln('file not found');
AddLog(FormatDateTime('yyyy-MM-dd HH:mm:ss',Now) + ' File: '+s+' not found! '
+ AContext.Binding.PeerIP + ':' + IntToStr(AContext.Binding.PeerPort));
end;
end;
end;
end;
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, StdCtrls, ScktComp;type
TDataInfo=record
DataName:String[255];
FileName:String[255];
FileSize:Int64;
end;
TForm1 = class(TForm)
btnAsk: TButton;
cs: TClientSocket;
procedure btnAskClick(Sender: TObject);
procedure csRead(Sender: TObject; Socket: TCustomWinSocket);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;
implementation{$R *.dfm}procedure TForm1.btnAskClick(Sender: TObject);
var
A: TDataInfo;
B: TMemoryStream;
i: Integer;
begin
try
B := TMemoryStream.Create;
try
cs.Address := '10.137.199.232';
cs.Port := 8750;
cs.Open;
A.DataName := 'AskFile';
A.FileName := 'aa';
A.FileSize := 0;
B.WriteBuffer(A,SizeOf(A));
cs.Socket.SendStream(B);
except
on E: Exception do
ShowMessage(E.Message);
end;
finally
FreeAndNil(B);
end;
end;procedure TForm1.csRead(Sender: TObject; Socket: TCustomWinSocket);
var
A: TMemoryStream;
B: TDataInfo;
C: PChar;
D: Integer;
begin
try
A := TMemoryStream.Create;
Socket.ReceiveBuf(B,SizeOf(B));
if B.DataName = 'SendFile' then
begin
GetMem(C, 4096);
repeat
Socket.ReceiveBuf(C, 4096);
A.WriteBuffer(C, 4096);
until A.Size >= B.FileSize; A.SaveToFile('File\'+B.FileName);
end;
finally
FreeAndNil(A);
end;
end;end.
//客户端结束unit Unit1;//服务器端interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ScktComp;type
TDataInfo=record
DataName:String[255];
FileName:String[255];
FileSize:Int64;
end;
TForm1 = class(TForm)
ss: TServerSocket;
procedure FormCreate(Sender: TObject);
procedure ssGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
private
{ Private declarations }
public
{ Public declarations }
end; TMyThread = class(TServerClientThread)
private
FStream: TWinSocketStream;
public
procedure ClientExecute; override;
end;
var
Form1: TForm1;implementation{$R *.dfm}{ TMyThread }procedure TMyThread.ClientExecute;
var
A, B: TDataInfo;
C: TFileStream;
begin
inherited FreeOnTerminate := true;
try
FStream := TWinSocketStream.Create(ClientSocket, 10000);
C := TFileStream.Create('File\Test.doc', fmOpenRead or fmShareDenyNone);
while(not Terminated) and (ClientSocket.Connected) do
begin
try
FStream.ReadBuffer(A,SizeOf(A));
if A.DataName = 'AskFile' then
begin
B.DataName := 'SendFile';
B.FileName := 'Test.doc';
B.FileSize := C.Size;
FStream.WriteBuffer(B, SizeOf(B));
FStream.CopyFrom(C,B.FileSize);
end;
except
on E:exception do
begin
ClientSocket.Close;
Terminate;
end;
end;
end;
finally
FreeAndNil(FStream);
FreeAndNil(C);
end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
ss.Open;
end;procedure TForm1.ssGetThread(Sender: TObject;
ClientSocket: TServerClientWinSocket;
var SocketThread: TServerClientThread);
begin
SocketThread := TMyThread.Create(False, ClientSocket);
end;end.
//服务器端结束