WINSOCK是一組API,用於在INTE.Net上傳輸數據和交換信息。用它編程本來是很麻煩的,但在DELPHHI中並不需要直接與WINSOCK的API打交道,因為TclientSocket和TserverSocket元件封裝了它的大部分API,使得對WINSOCK的訪問大大簡化。
SOCKET是網絡通信的基本構件,是可以被命名和尋址的通信端點,使用中的第一個SOCKET都有其類型和一個與之相連的進程。SOCKET存在於通信區域中,通信區域也叫地址族,是一個抽象概念,主要用於將通過SOCKET通信線程的共有特性綜合在一起。SOCKET通常只與同一區域中的SOCKET交換數據,也有可能跨區域通信,但這只是在執行了某種轉換進程后才能實現。
要通過網絡傳輸數據,至少需要一對SOCKET。其中,一個SOCKET在客戶端,另一個SOCKET在服務器端。一旦客戶端和服務器端都接通了SOCKET,它們之間就可以相互通信,其連接是建立在TCP/IP協議基礎上的,同時也支持其他相關協議,如XNS、DE.Net及IPX/SPX等。
本系統就是基於上述原理的,它由兩部分組成:駐留端和控制端。
駐留端放在需要監控的機器上,WINDOWS啟動時自動運行,並且要很好的隱藏起來:不出現的任務欄上,當用戶按下CTRL+ALT+DEL時,也不能從任務列表中發現。
控制端放在管理員的機器上,管理員通過指令可以觀察或控制被監控的機器。指令有五個:
截取屏幕:可以觀察到被控機的當前屏幕,看操作員在干什么。
遠程關機:可以關閉被控的計算機。
遠程重啟:可以重新啟動被控的計算機。
鎖定機器:封鎖被控機的操作,鍵盤、鼠標操作都無效。
機器解鎖:解除對被控機的封鎖。
代碼編寫
1、 控制端
主窗體設計如效果圖,各控件名稱如下表:
名稱 控件類型 標題 用途
HscrollB TScrollBar; 滾動圖像
VScrollB TscrollBar 滾動圖像
Label1 Tlabel 顯示文字
Ipbox TcomboBox 顯示IP地址列表
RadioGroup1 TRadioGroup 美化界面
Cuts TradioButton 截屏選擇
Cloma TradioButton 關機選擇
Restart TradioButton 啟動選擇
Lock TradioButton 鎖定選擇
Unlock TradioButton 解鎖選擇
Button1 Tbutton 添加IP地址
Button2 Tbutton 執行指令
Button3 Tbutton 關閉界面
Button4 Tbutton 連接監控端
ImPanel TPanel 美化界面
Image Timage 顯示圖像
Panel1 TPanel 顯示狀態
Kz TclientSocket 建立連接
tccd TPopupMenu 彈出菜單
控制端代碼不太復雜,主要在為了顯示從被監控機器傳過來的數據時有點復雜,下面單獨說明一下:
procedure TForm1.kzRead(Sender: TObject; Socket: TCustomWinSocket);
var buf:array[0..buffer-1] of char;//定義一個緩沖區,大小為2048字節
temp:integer;
begin
temp:=socket.ReceiveLength;//得到傳來數據的長度
panel1.Caption:=‘正在接收來自‘+ipbox.Text+‘的圖像數據,稍侯……‘;
bmpmap.WriteBuffer(buf,Socket.ReceiveBuf(buf,temp));把緩沖區的數據寫入流
if temp<buffer then//如果數據長度小於緩沖區,說明數據已傳完,顯示圖像
begin
bmpmap.Position:=0;
ScrollReset;
image.Picture.Bitmap.LoadFromStream(bmpmap);
bmpmap.clear;
panel1.Caption:=‘圖像已經成功的接收!‘;
end
else Socket.SendText(‘cut‘);//否則繼續要求傳輸
end;
在顯示圖像時,是通過滾動條和圖像控件組合使用的,請注意代碼
當然,為了讓軟件更專業,要有托盤圖標,這使代碼復雜一些,這些功能在本系統中都實現了,請留意源代碼。下面給出該系統的源代碼:(代碼容易看明白,不詳細解釋了)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
StdCtrls, ExtCtrls, ComCtrls, ScktComp,shellapi, Menus;
const wm_icb=wm_user+1000;
type
TForm1 = class(TForm)
hScrollB: TScrollBar;
vScrollB: TScrollBar;
Label1: TLabel;
ipbox: TComboBox;
RadioGroup1: TRadioGroup;
cuts: TRadioButton;
cloma: TRadioButton;
restart: TRadioButton;
lock: TRadioButton;
unlock: TRadioButton;
Button1: TButton;
Button2: TButton;
Button3: TButton;
imPanel: TPanel;
Image: TImage;
Panel1: TPanel;
kz: TClientSocket;
Button4: TButton;
tccd: TPopupMenu;
N1: TMenuItem;
N2: TMenuItem;
N3: TMenuItem;
N4: TMenuItem;
N5: TMenuItem;
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure vScrollBChange(Sender: TObject);
procedure hScrollBScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure kzRead(Sender: TObject; Socket: TCustomWinSocket);
procedure kzDisconnect(Sender: TObject; Socket: TCustomWinSocket);
procedure kzConnect(Sender: TObject; Socket: TCustomWinSocket);
procedure cutsClick(Sender: TObject);
procedure clomaClick(Sender: TObject);
procedure restartClick(Sender: TObject);
procedure lockClick(Sender: TObject);
procedure unlockClick(Sender: TObject);
procedure kzConnecting(Sender: TObject; Socket: TCustomWinSocket);
procedure kzError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
procedure ipboxChange(Sender: TObject);
procedure N3Click(Sender: TObject);
procedure N2Click(Sender: TObject);
procedure N1Click(Sender: TObject);
private
Units: TPoint;
myicon:TNotifyicondata;
procedure wmicb(var msg:TMessage);message wm_icb;
procedure ScrollReset;
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses Unit2, Unit3;
{$R *.DFM}
const
DEF_SCROLL_UNITS = 8;
buffer=2048;
var bmpmap:TMemorystream;
procedure display;
begin
if form1.visible=true then
form1.n1.Caption:=‘顯示(&D)‘
else
form1.n1.Caption:=‘隱藏(&H)‘;
form1.visible:=not form1.visible;
application.ShowMainForm:=form1.visible;
setforegroundwindow(application.handle);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
display;
end;
procedure TForm1.Button3Click(Sender: TObject);
begin
if not assigned(form2) then form2:=Tform2.Create(application);
form2.show;
end;
procedure TForm1.vScrollBChange(Sender: TObject);
begin
Image.Top := -Units.y * VScrollb.Position;
end;
procedure TForm1.hScrollBScroll(Sender: TObject; ScrollCode: TScrollCode;
var ScrollPos: Integer);
begin
Image.Left := -Units.x * ScrollPos
end;
procedure TForm1.ScrollReset;
begin
Units.x := DEF_SCROLL_UNITS;
Units.y := DEF_SCROLL_UNITS;
if Image.Picture <> nil then
begin
Image.Top := 0;
Image.Left := 0;
HScrollb.Position := 0;
VScrollb.Position := 0;
HScrollb.Min := 0;
VScrollb.Min := 0;
HScrollb.Visible := True;
VScrollb.Visible := True;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if cuts.Checked then
begin
panel1.Caption:=‘截取‘+ipbox.Text+‘計算機的屏幕!‘;
bmpmap.Clear;
kz.Socket.SendText(‘cut‘);
end
else if cloma.Checked then
begin
panel1.Caption:=‘關閉‘+ipbox.Text+‘的計算機!‘;
kz.Socket.SendText(‘ygj‘);
kz.Active:=false;
end
else if restart.Checked then
begin
panel1.Caption:=‘重新啟動‘+ipbox.Text+‘的計算機!‘;
kz.Socket.SendText(‘yqd‘);
kz.Active:=false;
end
else if lock.Checked then
begin
panel1.Caption:=‘鎖定‘+ipbox.Text+‘的計算機!‘;
kz.Socket.SendText(‘sdj‘);
end
else if unlock.Checked then
begin
panel1.Caption:=‘解鎖‘+ipbox.Text+‘的計算機!‘;
kz.Socket.SendText(‘jsj‘);
end
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
myicon.cbSize:=sizeof(TNotifyicondata);
myicon.Wnd:=handle;
myicon.uID:=1;
myicon.uFlags:=nif_message or nif_tip or nif_icon;
myicon.uCallbackMessage:=wm_icb;
myicon.hIcon:=application.Icon.Handle;
myicon.szTip:=‘大眼睛 V1.0‘;
shell_notifyicon(nim_add,@myicon);
setwindowlong(application.handle,gwl_exstyle,ws_ex_toolwindow);
bmpmap:=TMemorystream.Create;
ipbox.Items.LoadFromFile(‘pzwj.ini‘);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
bmpmap.free;
shell_notifyicon(nim_delete,@myicon);
end;
procedure TForm1.Button4Click(Sender: TObject);
begin
if ipbox.Text=‘‘ then exit;
if button4.Caption=‘連接(&C)‘ then
begin
kz.Address:=ipbox.Text;
kz.Active:=true;
button1.Enabled:=true;
end
else
begin
kz.Active:=false;
button1.Enabled:=false;
end;
end;
procedure TForm1.kzRead(Sender: TObject; Socket: TCustomWinSocket);
var buf:array[0..buffer-1] of char;
temp:integer;
begin
temp:=socket.ReceiveLength;
panel1.Caption:=‘正在接收來自‘+ipbox.Text+‘的圖像數據,稍侯……‘;
bmpmap.WriteBuffer(buf,Socket.ReceiveBuf(buf,temp));
if temp<buffer then
begin
bmpmap.Position:=0;
ScrollReset;
image.Picture.Bitmap.LoadFromStream(bmpmap);
bmpmap.clear;
panel1.Caption:=‘圖像已經成功的接收!‘;
end
else Socket.SendText(‘cut‘);
end;
procedure TForm1.kzDisconnect(Sender: TObject; Socket: TCustomWinSocket);
begin
button4.Caption:=‘連接(&C)‘;
panel1.Caption:=‘已經和‘+ipbox.Text+‘斷開連接‘;
end;
procedure TForm1.kzConnect(Sender: TObject; Socket: TCustomWinSocket);
begin
button4.Caption:=‘斷開(&D)‘;
panel1.Caption:=‘已經成功的連接到‘+ipbox.Text;
end;
procedure TForm1.cutsClick(Sender: TObject);
begin
panel1.Caption:=‘截取遠程計算機的屏幕‘;
end;
procedure TForm1.clomaClick(Sender: TObject);
begin
panel1.Caption:=‘關閉遠程計算機‘;
end;
procedure TForm1.restartClick(Sender: TObject);
begin
panel1.Caption:=‘重新啟動遠程計算機‘;
end;
procedure TForm1.lockClick(Sender: TObject);
begin
panel1.Caption:=‘鎖定遠程計算機‘;
end;
procedure TForm1.unlockClick(Sender: TObject);
begin
panel1.Caption:=‘恢復遠程計算機‘;
end;
procedure TForm1.kzConnecting(Sender: TObject; Socket: TCustomWinSocket);
begin
panel1.Caption:=‘正在連接‘+ipbox.Text;
end;
procedure TForm1.kzError(Sender: TObject; Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
kz.Active:=false;
panel1.Caption:=‘網絡連接出錯,請重試!‘;
end;
procedure TForm1.ipboxChange(Sender: TObject);
begin
button4.Caption:=‘連接(&C)‘;
kz.active:=false;
end;
procedure TForm1.wmicb(var msg:TMessage);
var tcwz:TPoint;
begin
case msg.LParam of
wm_lbuttonup:
display;
wm_rbuttonup:
begin
getcursorpos(tcwz);
tccd.Popup(tcwz.x,tcwz.y);
end;
end;
end;
procedure TForm1.N3Click(Sender: TObject);
begin
procedure TForm1.kzClientRead(Sender: TObject;
Socket: TCustomWinSocket);
var buf:array[0..buffer-1] of char;//開辟一個緩沖區來保存要發送的數據
sendsize,temp:integer;
temps:string;
begin
temps:=Socket.ReceiveText;
if temps=‘cut‘ then //如果是截屏指令
begin
if bmpstream.Size=0 then screencap(0,0,800,600);//如果沒生成圖像就截屏
if leftsize>buffer then sendsize:=buffer
else sendsize:=leftsize;
bmpstream.ReadBuffer(buf,sendsize);//從內存流中將數據讀入緩沖區
leftsize:=leftsize-sendsize;
if leftsize=0 then bmpstream.clear;
socket.Sendbuf(buf,sendsize);//發送數據
end
else if temps=‘ygj‘ then ExitWindowsEx(EWX_SHUTDOWN,0)//關閉機器
else if temps=‘yqd‘ then ExitWindowsEx(EWX_REBOOT,0)//重新啟動機器
else if temps=‘sdj‘ then//如果是鎖定機器指令
begin
enablewindow(getdesktopwindow,false);
end
else if temps=‘jsj‘ then//如果是解除指令
begin
enablewindow(getdesktopwindow,true);
end
end;
end.
http://blog.sina.com.cn/s/blog_562349090100zufn.html