//客户端
代码
unit UntClt;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient,
StdCtrls, UntGlb, IdGlobal, ExtCtrls, ImgList, jpeg, WinSock, IdIPWatch;
type
TForm1 = class(TForm)
stat1: TStatusBar;
img1: TImage;
lbl1: TLabel;
btn1: TButton;
chk1: TCheckBox;
edt1: TEdit;
btn2: TButton;
btn3: TButton;
btn4: TButton;
btn5: TButton;
grp1: TGroupBox;
lst1: TListBox;
idtcpclnt1: TIdTCPClient;
BalloonHint1: TBalloonHint;
il1: TImageList;
dlgOpen1: TOpenDialog;
ProgressBar1: TProgressBar;
btnCancle: TButton;
IdIPWatch1: TIdIPWatch;
procedure btn1Click(Sender: TObject);
procedure chk1Click(Sender: TObject);
procedure idtcpclnt1Disconnected(Sender: TObject);
procedure btn2Click(Sender: TObject);
procedure idtcpclnt1Connected(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btn5Click(Sender: TObject);
procedure btn3Click(Sender: TObject);
procedure btn4Click(Sender: TObject);
procedure WMMOVE(var msg: TMessage); message WM_MOVE;
procedure WMUSERMSG(var msg: TMessage); message WM_USERMSG;
procedure ShowProgressBar(Visible: Boolean);
procedure btnCancleClick(Sender: TObject);
private
{ Private declarations }
ComputerName: string;
public
{ Public declarations }
UserBreakAll: Boolean;
end;
TFileThread = class(TThread)
private
// CB: TDataPack;
protected
procedure Execute; override;
end;
TMonitorThread = class(TThread)
protected
procedure Execute; override;
end;
var
Form1: TForm1;
FileThread: TFileThread;
MonitorThread: TMonitorThread;
AllowDisconnectedEvent: Boolean = False;
function SendARP(Destip, scrip: DWORD; pmacaddr: PDWORD;
VAR phyAddrlen: DWORD): DWORD; stdcall; external 'iphlpapi.dll';
implementation
{$R *.dfm}
function GetMacFromIP(IP: AnsiString): AnsiString;
type
Tinfo = array [0 .. 7] of Byte;
var
dwTargetIP: DWORD;
dwMacAddress: array [0 .. 1] of DWORD;
dwMacLen: DWORD;
dwResult: DWORD;
X: Tinfo;
stemp: AnsiString;
iloop: integer;
begin
dwTargetIP := Inet_Addr(PAnsiChar(IP));
dwMacLen := 6;
dwResult := SendARP(dwTargetIP, 0, @dwMacAddress[0], dwMacLen);
case dwResult of
NO_ERROR:
begin
// ShowMessage('查到');
X := Tinfo(dwMacAddress);
for iloop := 0 to 5 do
begin
stemp := stemp + inttohex(X[iloop], 2);
end;
Result := stemp;
end;
ERROR_BAD_NET_NAME:
Result := '目标IPv4地址无法送达(Windows Vista 及以后版本错误)';
ERROR_BUFFER_OVERFLOW:
Result := 'PhyAddrLen参数小于6(Windows Vista 及以后版本错误)';
ERROR_GEN_FAILURE:
Result := '目标IPv4地址无法送达(Windows Server 2003及之前版本错误)';
ERROR_INVALID_PARAMETER:
Result := 'pMacAddr或PhyAddrLen参数是一个NULL指针(Windows Server 2003及之前版本错误)';
ERROR_INVALID_USER_BUFFER:
Result := 'PhyAddrLen参数为零(Windows Server 2003及之前版本错误)';
// ERROR_NOT_FOUND:Result :='非INADDR_ANY的IP地址(IPv4地址为0.0.0.0)(Windows Vista 错误)';
ERROR_NOT_SUPPORTED:
Result := '本机操作系统不支持该函数';
else
Result := '未知';
end;
end;
function GetWindowsVersionString: AnsiString;
var
VI: TOSVersionInfoA;
begin
VI.dwOSVersionInfoSize := SizeOf(TOSVersionInfoA);
if GetVersionExA(VI) then
with VI do
Result := Trim(Format('%d.%d build %d %s', [dwMajorVersion,
dwMinorVersion, dwBuildNumber, szCSDVersion]))
else
Result := '';
end;
function GetWindowsVersion: String; // 读取操作系统版本
var
AWin32Version: Extended;
os: string;
begin
os := 'Windows ';
AWin32Version := StrtoFloat(Format('%d.%d', [Win32MajorVersion,
Win32MinorVersion]));
if Win32Platform = VER_PLATFORM_WIN32s then
Result := os + '32'
else if Win32Platform = VER_PLATFORM_WIN32_WINDOWS then
begin
if AWin32Version = 4.0 then
Result := os + '95'
else if AWin32Version = 4.1 then
Result := os + '98'
else if AWin32Version = 4.9 then
Result := os + 'Me'
else
Result := os + '9x'
end
else if Win32Platform = VER_PLATFORM_WIN32_NT then
begin
if AWin32Version = 3.51 then
Result := os + 'NT 3.51'
else if AWin32Version = 4.0 then
Result := os + 'NT 4.0'
else if AWin32Version = 5.0 then
Result := os + '2000'
else if AWin32Version = 5.1 then
Result := os + 'XP'
else if AWin32Version = 5.2 then
Result := os + '2003'
else if AWin32Version = 6.0 then
Result := os + 'Vista'
else if AWin32Version = 6.1 then
Result := os + '7'
else
Result := os;
end
else
Result := os + '??';
Result := Result + ' ' + GetWindowsVersionString;
end;
procedure TForm1.btn1Click(Sender: TObject);
begin
close;
end;
procedure TForm1.btn2Click(Sender: TObject);
var
i: integer;
begin
if dlgOpen1.Execute(Handle) then
begin
for i := 0 to dlgOpen1.Files.Count - 1 do
lst1.Items.add(dlgOpen1.Files[i]);
end;
grp1.Caption := GroupText + Format(FileListString, [lst1.Count]);
end;
procedure TForm1.btn3Click(Sender: TObject);
begin
lst1.Clear;
grp1.Caption := GroupText + Format(FileListString, [0]);
end;
procedure TForm1.btn4Click(Sender: TObject);
begin
lst1.DeleteSelected;
grp1.Caption := GroupText + Format(FileListString, [lst1.Count]);
end;
procedure TForm1.btn5Click(Sender: TObject);
var
DlgText: string;
begin
if idtcpclnt1.Connected then
begin
if lst1.Count > 0 then
begin
DlgText := Format(DlgSendFileText, [lst1.Count]);
if Application.MessageBox(PChar(DlgText), '发送提示',
MB_OKCANCEL + MB_ICONQUESTION) = IDOK then
begin
ShowProgressBar(True);
FileThread := TFileThread.Create(True);
FileThread.FreeOnTerminate := True;
FileThread.Start;
end;
end
else
ShowMessage(DlgSelectFile);
end
else
ShowMessage(DlgNoConnected);
end;
procedure TForm1.btnCancleClick(Sender: TObject);
begin
UserBreakAll := True;
end;
procedure TForm1.chk1Click(Sender: TObject);
begin
idtcpclnt1.Host := edt1.Text;
if chk1.Checked then
begin
try
Application.ProcessMessages;
idtcpclnt1.Connect;
AllowDisconnectedEvent := True;
stat1.Panels[1].Text := StaConnected;
except
ShowMessage(DlgConnectFailed);
end;
end
else
begin
AllowDisconnectedEvent := False;
idtcpclnt1.Disconnect;
end;
chk1.Checked := idtcpclnt1.Connected;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
n: Cardinal;
Name: array [0 .. MAX_COMPUTERNAME_LENGTH] of Char;
begin
n := MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(name, n);
ComputerName := string(Name);
MonitorThread := TMonitorThread.Create(True);
MonitorThread.FreeOnTerminate := True;
MonitorThread.Start;
end;
procedure TForm1.idtcpclnt1Connected(Sender: TObject);
var
bbuf: TIdBytes;
buf: TDataPack;
begin
bbuf := nil;
FillChar(buf, SizeOf(buf), '');
buf.Command := cmdSetName;
StrPCopy(buf.ClientInfo.ClientName ,ComputerName);
StrPCopy(buf.ClientInfo.ClientOS,GetWindowsVersion);
StrPCopy(buf.ClientInfo.ClientACTIP ,GetMacFromIP(IdIPWatch1.LocalIP));
bbuf := RawToBytes(buf, SizeOf(buf));
idtcpclnt1.IOHandler.Write(bbuf);
end;
procedure TForm1.idtcpclnt1Disconnected(Sender: TObject);
begin
stat1.Panels[1].Text := StaDisconnected;
chk1.Checked := False;
end;
procedure TForm1.ShowProgressBar(Visible: Boolean);
begin
ProgressBar1.Visible := Visible;
btnCancle.Visible := Visible;
end;
procedure TForm1.WMMOVE(var msg: TMessage);
begin
// inherited;
// if Assigned(frmProgress) then
// frmProgress.Position := poMainFormCenter;
end;
procedure TForm1.WMUSERMSG(var msg: TMessage);
begin
case msg.WParam of
1:
ShowMessage(Format(DlgFileSendOk, [msg.LParam]));
2:
stat1.Panels[1].Text := string(PChar(msg.LParam));
3:
ProgressBar1.Position := msg.LParam;
4:
ProgressBar1.Max := msg.LParam;
5:
idtcpclnt1.OnDisconnected(Self);
6:
ShowMessage(DlgExcept);
7:
ShowProgressBar(False);
end;
end;
{ TFileThread }
procedure TFileThread.Execute;
var
FileName: string;
buf: TDataPack;
bbuf: TIdBytes;
i, j, SendTimes, RemainLen, h, FileLen, SentFilesNum,
ClientReadedBytes: integer;
begin
try
Form1.UserBreakAll := False;
SentFilesNum := 0;
for i := 0 to Form1.lst1.Count - 1 do
begin
if Form1.UserBreakAll then
Break;
FileName := Form1.lst1.Items[i];
// frmProgress.lbl1.Caption := FileName;
// frmProgress.pb1.Position := 0;
PostMessage(Form1.Handle, WM_USERMSG, 2, integer(PChar(FileName)));
PostMessage(Form1.Handle, WM_USERMSG, 3, 0);
h := FileOpen(FileName, fmOpenRead);
if h > 0 then
begin
try
FileLen := GetFileSize(h, nil);
SendTimes := FileLen div SEND_BUF;
RemainLen := FileLen mod SEND_BUF;
// frmProgress.pb1.Max := FileLen;
PostMessage(Form1.Handle, WM_USERMSG, 4, FileLen);
FillChar(buf.ClientInfo, SizeOf(buf.ClientInfo), '');
buf.Command := cmdSendFile;
StrPCopy(buf.FileName,ExtractFileName(FileName));
buf.FileSize := FileLen;
buf.Flags := 0; // 新建
for j := 1 to SendTimes do
begin
if Form1.UserBreakAll then
Break;
if not Form1.idtcpclnt1.Connected then
Break;
ClientReadedBytes := FileRead(h, buf.FileData, SEND_BUF);
buf.ReadBytes := ClientReadedBytes;
bbuf := nil;
bbuf := RawToBytes(buf, SizeOf(buf));
Form1.idtcpclnt1.IOHandler.Write(bbuf);
buf.Flags := 1; // 续传
// frmProgress.pb1.Position := j * SEND_BUF;
PostMessage(Form1.Handle, WM_USERMSG, 3, j * SEND_BUF);
end;
if RemainLen > 0 then
begin
if not Form1.idtcpclnt1.Connected then
Break;
ClientReadedBytes := FileRead(h, buf.FileData, RemainLen);
buf.ReadBytes := ClientReadedBytes;
bbuf := nil;
bbuf := RawToBytes(buf, SizeOf(buf));
Form1.idtcpclnt1.IOHandler.Write(bbuf);
PostMessage(Form1.Handle, WM_USERMSG, 3, FileLen);
end;
finally
FileClose(h);
end;
if (not Form1.UserBreakAll) then
inc(SentFilesNum);
end;
end;
PostMessage(Form1.Handle, WM_USERMSG, 7, 0);
PostMessage(Form1.Handle, WM_USERMSG, 1, SentFilesNum);
if Form1.idtcpclnt1.Connected and Form1.UserBreakAll then
begin
bbuf := nil;
buf.Command := cmdUserbreak;
bbuf := RawToBytes(buf, SizeOf(buf));
Form1.idtcpclnt1.IOHandler.Write(bbuf);
end;
except
PostMessage(Form1.Handle, WM_USERMSG, 7, 0);
PostMessage(Form1.Handle, WM_USERMSG, 6, 0);
AllowDisconnectedEvent := False;
Form1.idtcpclnt1.Disconnect;
Terminate;
end;
end;
{ TMonitorThread }
procedure TMonitorThread.Execute;
begin
while not Terminated do
begin
if not Form1.idtcpclnt1.Connected then
if AllowDisconnectedEvent then
begin
AllowDisconnectedEvent := False;
PostMessage(Form1.Handle, WM_USERMSG, 5, 0);
end;
Sleep(100);
end;
end;
end.
//公共单元
代码
unit UntGlb;
interface
uses
Messages,Windows, SysUtils,Classes ;
const
WM_USERMSG = WM_USER +1002;
WM_USERFILE= WM_USER +1003;
ADD_LIST = 0;
DEL_LIST =1;
UPD_STA =2;
SHOW_R =3;
SEND_BUF = 1024*20;
REV = 'REV';
IniFileName = 'Server.ini';
type
TCommand = (cmdSetName,cmdSendFile,cmdUserbreak,cmdGetClientInfo);
TClientInfo = packed record
ClientName : array[0..49] of Char;
ClientIP : array[0..14] of Char;
ClientID : array[0..9] of Char;
ClientACTIP : array[0..17] of Char;
ClientOS : array[0..49] of Char;
ClientStatus : array[0..9] of Char;
ReceivedFileName : array[0..255] of Char;
ReceivedPersent,
ReceivedFileSize : Cardinal;
Flags : Integer;
IdleTime : TTime;
Isbusy : Boolean;
end;
TDataPack = packed record
Flags : Integer;
FileSize,
ReadBytes : Cardinal;
Command : TCommand;
ClientInfo : TClientInfo;
FileName : array[0..255] of Char;
FileData : array[0..SEND_BUF -1] of Byte;
end;
resourcestring
MainFormCaption = 'Indy10.5.5 IdTcpServer Demo';
StringsObjectName = 'object';
GroupText = '发送文件列表';
FileListString = '(%d个文件)';
DlgCreateIniFailed = '创建配置文件失败,请检查磁盘空间';
DlgIniFileBreak = '配置文件损坏,重新创建失败';
DlgIniNotExists = '配置文件不存在';
DlgIniBusy = '配置文件被占用';
DlgSendFileText = '您确定要发送列表中的%d个文件吗?';
DlgSendFileCaption = '发送提示';
DlgFileSendOk = '%d个文件发送成功';
DlgSelectFile = '请选择待发送的文件';
DlgNoConnected = '未连接服务器';
DlgFileExists = '文件%s已存在,要替换吗?';
DlgLogOk = '日志保持成功';
DlgLogFailed = '日志保存失败';
DlgConnectFailed = '连接被拒绝,可能服务器没有开启';
DlgExcept = '服务器端异常断开,文件传输中止!';
StaInitText = '服务器未开启';
StaText = '客户端连接数:%d个';
StaConnected = '已链接到服务器';
StaDisconnected = '已从服务器断开';
StaServerStart = '服务器开启';
StaServerClose = '服务器关闭';
StaReceivedPersent = '接收文件:%s--(%u%%)';
LogTxt = '------服务器操作日志------'+#13+#10;
LogServerStart = '【服务器开启--%s】';
LogServerClose = '【服务器关闭--%s】';
LogClientdisConnected = '【客户端:%s,%s】从服务器断开--%s';
LogClientConnected = '【客户端:%s,%s】连接到服务器--%s';
LogReceiveFile = '【客户端:%s】正在发送文件: %s(大小:%u字节)--%s';
LogReceiveFileOk = '【客户端:%s】发送的文件: %s 接收完毕,保存在REV子目录下--%s';
LogUerBreakSend = '【客户端:%s】用户终止文件: %s 传送--%s';
LogClientStateSleep = '空闲';
LogClientStateBusy = '数据传输中';
LogClientTimeOut = '客户端空闲超时,断开连接...' ;
bhBalloonHint = '欢迎使用,双击显示界面';
bhBalloonTitle = 'Indy10.5.5Demo';
dlgInputBoxCpt = '客户端连接数设置';
dlgInputBox = '最大连接数';
implementation
end.
//关于
代码
unit About;
interface
uses Windows, SysUtils, Classes, Graphics, Forms, Controls, StdCtrls,
Buttons, ExtCtrls;
type
TAboutBox = class(TForm)
Panel1: TPanel;
ProgramIcon: TImage;
ProductName: TLabel;
Version: TLabel;
Copyright: TLabel;
Comments: TLabel;
OKButton: TButton;
procedure OKButtonClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
AboutBox: TAboutBox;
implementation
{$R *.dfm}
procedure TAboutBox.OKButtonClick(Sender: TObject);
begin
CloseModal;
end;
end.