www.pudn.com > ControlRemote.zip > Server.c


//服务器端:发送本机桌面到连接的客户端 
#include  
#include  
#include  
#include  
#include "Server.h" 
#include "Command.h" 
#include "Gdi.h" 
#include "HuffCompress.h" 
#include "RLE.h" 
//默认端口 
#define DEFAULT_PORT        5150 
#define SETFLAGS			XP1_GUARANTEED_DELIVERY|XP1_GUARANTEED_ORDER 
#define NOTSETFLAGS			XP1_CONNECTIONLESS 
#define	LPBMIH				LPBITMAPINFOHEADER 
 
UINT    gPort  = DEFAULT_PORT; 
int		nGridX = 8; 
int		nGridY = 2; 
DWORD	dwLen,dwCompress,dwSendLen; 
int		iCompressionLevel = 10; 
HWND	hServerWnd; 
HDC		hDDC = NULL,hMemDC,hNullDC; 
BOOL	fChange = FALSE; 
SOCKET	Socket; 
SOCKET	Listen; 
int		iWidth,iHeight; 
WORD	bmBitsPixel = 4; 
// 指向全局位图 
BOOL	fDIBitmap = FALSE; 
 
// GDI区域结构 
struct	GdiList	GdiStart; 
struct	GdiList	*pGdiNode; 
 
// 这个结构用来在LPARAM参数中传递信息到客户端线程 
struct	myStruct 
{ 
	SOCKET	Socket; 
	HWND	hWnd; 
}; 
 
int SelectProtocols(DWORD dwSetFlags,DWORD dwNotSetFlags,LPWSAPROTOCOL_INFO lpProtocolBuffer,LPDWORD lpdwBufferLength,WSAPROTOCOL_INFO *pProtocol); 
 
//LoadWinsock用来装载和初始化Winsock,绑定本地地址,创建监听socket,等候客户端连接 
DWORD WINAPI LoadWinsock(LPVOID lpParam) 
{ 
	// 协议变量 
	LPBYTE				pBuf; 
	WSAPROTOCOL_INFO	Protocol; 
	int					nRet; 
	int					nZero = 0; 
 
	int					iAddrSize; 
	HANDLE				hThread; 
	DWORD				dwThreadId; 
	char				szClientIP[81]; 
	char				szString[255]; 
	struct	sockaddr_in	local,client; 
	// 这个结构用来在LPARAM参数中传递信息到客户端线程 
	struct	myStruct	myStructure; 
 
	// 为协议的选择和所有协议的变量决定需要的缓冲区的大小 
	dwLen = 0; 
	nRet = WSAEnumProtocols(NULL,NULL,&dwLen); 
	if (nRet == SOCKET_ERROR) 
	{ 
		if (WSAGetLastError() != WSAENOBUFS) 
			return 1; 
	} 
	pBuf = malloc(dwLen); 
	// 为WSASocketGet()得到协议 
	nRet = SelectProtocols(SETFLAGS,NOTSETFLAGS,(LPWSAPROTOCOL_INFO)pBuf,&dwLen,&Protocol); 
 
	// 创建我们的监听socket 
	Listen = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_IP,NULL,0,SOCK_STREAM); 
	if (Listen == SOCKET_ERROR) 
	{ 
		sprintf(szString,"socket() failed: %d",WSAGetLastError()); 
		MessageBox(NULL,szString,"Remote Server",MB_OK); 
		return 1; 
	} 
 
	// 设置server端信息 
	local.sin_addr.s_addr = htonl(INADDR_ANY); 
	local.sin_family = AF_INET; 
	local.sin_port = htons(gPort); 
 
	// 绑定到socket 
	if (bind(Listen,(struct sockaddr *)&local,sizeof(local)) == SOCKET_ERROR) 
	{ 
		sprintf(szString,"bind() failed: %d\n", WSAGetLastError()); 
		MessageBox(NULL,szString,"Remote Server",MB_OK); 
		return 1; 
	} 
 
	//为了减小CPU的利用率,禁止在socket上将数据发送到缓冲。设置SO_SNDBUF为0, 
	//从而使winsock直接发送数据到客户端,而不是将数据缓冲才发送。 
	nZero = 0; 
	setsockopt(Listen,SOL_SOCKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero)); 
	//开始监听 
	listen(Listen,SOMAXCONN); 
 
	iAddrSize = sizeof(client); 
	while (TRUE) 
	{ 
		// 阻塞方式的接收客户端的连接,但因为这是一个线程函数,所以用户不会感到阻塞 
		Socket = accept(Listen,(struct sockaddr *)&client,&iAddrSize); 
		if (Socket != INVALID_SOCKET) 
		{ 
			// 设置传到客户端线程的信息的数据结构 
			myStructure.Socket = Socket; 
			myStructure.hWnd = hServerWnd; 
			//找出客户端的IP地址 
			memset(szClientIP,'\0',sizeof(szClientIP)); 
			sprintf(szClientIP,"%s",inet_ntoa(client.sin_addr)); 
			// 为每一个客户端创建一个线程 
			hThread = CreateThread(NULL,0,ClientThread,(LPVOID)&myStructure,0,&dwThreadId); 
			if (hThread) 
			{ 
				//关闭线程句柄 
				CloseHandle(hThread); 
			} 
		} 
		else 
			return 1; 
	} 
 
	return 0; 
} 
 
 
//客户端线程函数,这个函数等候从客户端程序发送过来的消息, 
//如果这个消息是"REFRESH",那么它发送当前的桌面图片 
//如果这个消息是"DISCONNECT",那么它结束和客户端的连接 
//如果这个消息以"WM_"开头,那么它就根据消息类型,在服务器端执行该消息 
DWORD WINAPI ClientThread(LPVOID lpParam) 
{ 
	HWND	hWnd; 
	SOCKET	MySocket; 
	FD_SET	SocketSet; 
	struct	timeval	timeout; 
	char	szMessage[2049]; 
	DWORD	iRecv; 
	struct	myStruct	*myStructure; 
	DWORD	iLength; 
	DWORD	iRet; 
	int		iUpdates; 
 
	// 分析参数 
	myStructure = (struct myStruct *)lpParam; 
	MySocket = myStructure->Socket; 
	hWnd = myStructure->hWnd; 
 
	// 设置超时值 
	timeout.tv_sec = 0;		// 秒 
	timeout.tv_usec = 0;	// 微秒 
 
	// 设置Socket集合 
	SocketSet.fd_count = 1; 
	SocketSet.fd_array[1] = MySocket; 
 
	// 轮询sockets 
	while(TRUE) 
	{ 
		// 等候发送过来的数据直到超时 
		iRet = select(0,&SocketSet,NULL,NULL,&timeout); 
		if (iRet != 0) 
		{ 
 			//初始化缓冲 
			memset(szMessage,'\0',sizeof(szMessage)); 
			// 阻塞方式调用recv() 
			iRecv = recv(MySocket,szMessage,2048,0); 
			szMessage[iRecv] = '\0'; 
 
			CHECK_MSG: 
			// 是不是"REFRESH"消息 
			if (strncmp(szMessage,"REFRESH",7) == 0) 
			{ 
				// 捕获并且发送桌面的更新的区域 
				iUpdates = SendRegionDisplay(hServerWnd,MySocket); 
			} 
			 
			// 检查从客户端发送过来的Windows 命令消息,这是一个核心部分 
			else if (strncmp(szMessage,"WM_",3) == 0) 
			{ 
				// 解析从客户端发送过来的消息并发送到本机的消息队列 
				DispatchWMMessage(szMessage); 
 
				// 看看是否还有消息 
				iLength = strlen(szMessage); 
				if (iLength > 0) 
					goto CHECK_MSG; 
			} 
			// 检查是否是查询消息 
			else if (strncmp(szMessage,"RESOLUTION",10) == 0) 
			{ 
				SendResolution(MySocket); 
			} 
			// 检查是否是DISCONNECT消息 
			else if (strncmp(szMessage,"DISCONNECT",10) == 0) 
			{ 
				fChange = FALSE; 
				fDIBitmap = FALSE; 
 
				pGdiNode = GdiStart.pNext; 
				while (pGdiNode) 
				{ 
					free(pGdiNode->Gdi.pDIBitmap); 
					free(pGdiNode->Gdi.pDIBChangeStart); 
					pGdiNode->Gdi.fDIBitmap = FALSE; 
					pGdiNode->Gdi.fChange = FALSE; 
					pGdiNode = pGdiNode->pNext; 
				} 
				// 停止查询,相当于结束该线程 
				break; 
			} 
		} 
	} 
	closesocket(MySocket); 
	return 0; 
} 
 
// 解析从客户端发送过来的消息并发送到本机的消息队列 
void DispatchWMMessage(char *szString) 
{ 
	//鼠标消息 
	struct {char *szWMMouseMsg;}  
	WMMouseMsg[] = {"WM_MM","WM_LBD","WM_LBU","WM_LBK", 
					"WM_MBD","WM_MBU","WM_MBK", 
					"WM_RBD","WM_RBU","WM_RBK"}; 
 
	// 键盘消息 
	struct {char *szWMKeyBdMsg;} 
	WMKeyBdMsg[] = {"WM_KD","WM_KU"}; 
 
	// 通用消息:色彩模式,网格数和压缩消息 
	struct {char *szMsg;} 
	Msg[] = {"WM_COMP","WM_GRID","WM_CMOD"}; 
 
	int		nWMMouseMsg; 
	int		nWMKeyBdMsg; 
	int		nMsg; 
 
	struct	CommandList	CommandStart; 
	struct	CommandList	*pCommandNode; 
	struct	CommandDS	Command; 
	char	*pDest; 
	int		iLoc,nChar; 
	int		iLoop,iParms; 
	char	szString2[2049]; 
 
	// 分别得到鼠标,键盘,通用消息的数目 
	nWMMouseMsg = (int)(sizeof(WMMouseMsg)/sizeof(WMMouseMsg[0])); 
	nWMKeyBdMsg = (int)(sizeof(WMKeyBdMsg)/sizeof(WMKeyBdMsg[0])); 
	nMsg = (int)(sizeof(Msg)/sizeof(Msg[0])); 
 
	// 初始化command链表 
	CommandStart.pNext = NULL; 
	pCommandNode = &CommandStart; 
 
	// 分析command命令,截获命令的参数 
	iParms = 0; 
	while (pDest = strchr(szString,';')) 
	{ 
		iLoc = pDest - szString; 
		nChar = iLoc; 
		memset(Command.szElement,'\0',sizeof(Command.szElement)); 
		strncpy(Command.szElement,szString,nChar); 
		// 发送到命令栈中 
		pCommandNode = Add_Command(pCommandNode,Command); 
		memset(szString2,'\0',sizeof(szString2)); 
		strcpy(szString2,&szString[iLoc + 1]); 
		strcpy(szString,szString2); 
 
		iParms++; 
		if (iParms == 5) // 每条命令5个参数 
			break; 
	} 
 
	// 处理命令 
	pCommandNode = CommandStart.pNext; 
	if (pCommandNode) 
	{ 
		// 鼠标消息 
		UINT	keyFlags; 
		int		iMessage; 
		int		fWMMouseMsg; 
		double	iScaleX,iScaleY,iX,iY; 
		DWORD	dwX,dwY; 
 
		// 键盘消息 
		int		fWMKeyBdMsg; 
		UINT	vk; 
		int		fDown; 
		int		cRepeat; 
		UINT	flags; 
 
		// 判断是否有鼠标消息 
		fWMMouseMsg = FALSE; 
		for (iLoop = 0;iLoop < nWMMouseMsg;iLoop++) 
		{ 
			if (strcmp(pCommandNode->Command.szElement,WMMouseMsg[iLoop].szWMMouseMsg) == 0) 
			{ 
				// 设置鼠标消息的标志 
				fWMMouseMsg = TRUE; 
				// 具体的鼠标消息 
				if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_MM\0") == 0) 
					iMessage = 1; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_LBD\0") == 0) 
					iMessage = 2; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_LBU\0") == 0) 
					iMessage = 3; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_LBK\0") == 0) 
					iMessage = 4; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_MBD\0") == 0) 
					iMessage = 5; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_MBU\0") == 0) 
					iMessage = 6; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_MBK\0") == 0) 
					iMessage = 7; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_RBD\0") == 0) 
					iMessage = 8; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_RBU\0") == 0) 
					iMessage = 9; 
				else if (strcmp(WMMouseMsg[iLoop].szWMMouseMsg,"WM_RBK\0") == 0) 
					iMessage = 10; 
 
				// 移动到参数栈的下一个节点,x坐标 
				pCommandNode = pCommandNode->pNext; 
				iX = atof(pCommandNode->Command.szElement); 
 
				// 移动到参数栈的下一个节点,y坐标 
				pCommandNode = pCommandNode->pNext; 
				iY = atof(pCommandNode->Command.szElement); 
 
				// 移动到参数栈的下一个节点,辅助键 
				pCommandNode = pCommandNode->pNext; 
				keyFlags = atoi(pCommandNode->Command.szElement); 
 
				// 退出循环 
				break; 
			} 
		} 
 
		// 如果有鼠标消息则对鼠标消息进行处理 
		if (fWMMouseMsg) 
		{ 
			// 得到坐标的范围因子 
			iScaleX = 65535.0 / (iWidth - 1); 
			iScaleY = 65535.0 / (iHeight - 1); 
			// 对坐标进行比例缩放 
			iX *= iScaleX; 
			iY *= iScaleY; 
			// 转换成DWORDS 
			dwX = (DWORD)iX; 
			dwY = (DWORD)iY; 
 
			// 处理鼠标消息 
			if (iMessage == 1)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MOVE,dwX,dwY,0,0); 
			} 
			else if (iMessage == 2)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,dwX,dwY,0,0); 
			} 
			else if (iMessage == 3)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,dwX,dwY,0,0); 
			} 
			else if (iMessage == 4)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_LEFTUP,dwX,dwY,0,0); 
			} 
			else if (iMessage == 5)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEDOWN,dwX,dwY,0,0); 
			} 
			else if (iMessage == 6)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEUP,dwX,dwY,0,0); 
			} 
			else if (iMessage == 7)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEUP,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_MIDDLEUP,dwX,dwY,0,0); 
			} 
			else if (iMessage == 8)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,dwX,dwY,0,0); 
			} 
			else if (iMessage == 9)  
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,dwX,dwY,0,0); 
			} 
			else if (iMessage == 10) 
			{ 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTDOWN,dwX,dwY,0,0); 
				mouse_event(MOUSEEVENTF_ABSOLUTE|MOUSEEVENTF_RIGHTUP,dwX,dwY,0,0); 
			} 
		} 
		else 
		{ 
			// 没有鼠标消息则判断是否有键盘消息 
			fWMKeyBdMsg = FALSE; 
			for (iLoop = 0;iLoop < nWMKeyBdMsg;iLoop++) 
			{ 
				if (strcmp(pCommandNode->Command.szElement,WMKeyBdMsg[iLoop].szWMKeyBdMsg) == 0) 
				{ 
					// 设置键盘消息标志 
					fWMKeyBdMsg = TRUE; 
					if (strcmp(WMKeyBdMsg[iLoop].szWMKeyBdMsg,"WM_KD\0") == 0) 
						iMessage = 1;//按下键 
					else if (strcmp(WMKeyBdMsg[iLoop].szWMKeyBdMsg,"WM_KU\0") == 0) 
						iMessage = 2;//松开键 
 
					// 移动到参数链表的下一个节点,Virtural 键码 
					pCommandNode = pCommandNode->pNext; 
					vk = atoi(pCommandNode->Command.szElement); 
 
					//移动到参数链表的下一个节点,按下键标志 
					pCommandNode = pCommandNode->pNext; 
					fDown = atoi(pCommandNode->Command.szElement); 
 
					// 移动到参数链表的下一个节点,按键重复数 
					pCommandNode = pCommandNode->pNext; 
					cRepeat = atoi(pCommandNode->Command.szElement); 
 
					// 移动到参数链表的下一个节点,标志位 
					pCommandNode = pCommandNode->pNext; 
					flags = atoi(pCommandNode->Command.szElement); 
 
					break; 
				} 
			} 
 
			// 如果有键盘消息,则处理键盘消息 
			if (fWMKeyBdMsg) 
			{ 
				if (iMessage == 1) //模拟按键消息 
				{ 
					keybd_event((BYTE)vk,(BYTE)vk,0,0); 
				} 
				else if (iMessage == 2) //模拟松开键的消息 
				{ 
					keybd_event((BYTE)vk,(BYTE)vk,KEYEVENTF_KEYUP,0); 
				} 
			} 
			else // 通用消息 
			{ 
				for (iLoop = 0;iLoop < nMsg;iLoop++) 
				{ 
					if (strcmp(pCommandNode->Command.szElement,Msg[iLoop].szMsg) == 0) 
					{ 
						if (strcmp(Msg[iLoop].szMsg,"WM_COMP\0") == 0) 
						{ 
							// 移动到参数链表的下一个节点,压缩级数 
							pCommandNode = pCommandNode->pNext; 
							iCompressionLevel = atoi(pCommandNode->Command.szElement); 
						} 
						else if (strcmp(Msg[iLoop].szMsg,"WM_GRID\0") == 0) 
						{ 
							// 移动到参数链表的下一个节点,x网格数 
							pCommandNode = pCommandNode->pNext; 
							nGridX = atoi(pCommandNode->Command.szElement); 
 
							// 移动到参数链表的下一个节点,y网格数 
							pCommandNode = pCommandNode->pNext; 
							nGridY = atoi(pCommandNode->Command.szElement); 
 
							// 清除当前的显示设置 
							ClearDisplay(hServerWnd); 
							// 初始化新的显示设置 
							InitDisplay(hServerWnd); 
						} 
						else if (strcmp(Msg[iLoop].szMsg,"WM_CMOD\0") == 0) 
						{ 
							// 移动到参数链表的下一个节点,每个屏幕点的字节数 
							pCommandNode = pCommandNode->pNext; 
							bmBitsPixel = atoi(pCommandNode->Command.szElement); 
 
							ClearDisplay(hServerWnd); 
							InitDisplay(hServerWnd); 
						} 
					} 
				} 
			} 
		} 
	} 
	// 清除命令队列 
	Clear_Command(&CommandStart); 
} 
 
// 初始化显示变量 
void InitDisplay(HWND hWnd) 
{ 
	struct	GdiDS	Gdi; 
	int		iWidthX,iHeightY,nGrid; 
	int		iXGrid,iYGrid,iLoop; 
 
	GdiStart.pNext = NULL; 
	pGdiNode = &GdiStart; 
	hDDC = CreateDC("DISPLAY",NULL,NULL,NULL); 
 
	// 得到屏幕的宽度和高度 
	iWidth = GetDeviceCaps(hDDC,HORZRES); 
	iHeight = GetDeviceCaps(hDDC,VERTRES); 
 
	// 分割屏幕成X网格区域 
	if (nGridX > 0) 
		iWidthX = iWidth/nGridX; 
	else 
		iWidthX = iWidth; 
 
	// 分割屏幕成Y网格区域 
	if (nGridY > 0) 
		iHeightY = iHeight/nGridY; 
	else 
		iHeightY = iHeight; 
 
	// 为网格创建区域的位图和Memory DC 
	if ((nGridX > 0) && (nGridY > 0)) 
	{ 
		for (iXGrid = 0;iXGrid < nGridX;iXGrid++) 
		{ 
			for (iYGrid = 0;iYGrid < nGridY;iYGrid++) 
			{ 
				Gdi.fChange = FALSE; 
				Gdi.fDIBitmap = FALSE; 
 
				Gdi.iGridX = iXGrid; 
				Gdi.iGridY = iYGrid; 
 
				Gdi.iWidth1 = iXGrid * iWidthX; 
				Gdi.iWidth2 = iXGrid * iWidthX + iWidthX; 
				Gdi.iHeight1 = iYGrid * iHeightY; 
				Gdi.iHeight2 = iYGrid * iHeightY + iHeightY; 
 
				Gdi.hMemDC = CreateCompatibleDC(hDDC); 
				Gdi.hDIBitmap = CreateCompatibleBitmap(hDDC,iWidthX,iHeightY); 
				SelectObject(Gdi.hMemDC,Gdi.hDIBitmap); 
 
				// 往队列中添加GDI信息 
				pGdiNode = Add_Gdi(pGdiNode,Gdi); 
			} 
		} 
	} 
	else  
	{ 
		nGrid = max(nGridX,nGridY); 
		for (iLoop = 0;iLoop < nGrid;iLoop++) 
		{ 
			Gdi.fChange = FALSE; 
			Gdi.fDIBitmap = FALSE; 
 
			if (nGridX > 0) 
			{ 
				Gdi.iGridX = iLoop; 
				Gdi.iWidth1 = iLoop * iWidthX; 
				Gdi.iWidth2 = iLoop * iWidthX + iWidthX; 
			} 
			else 
			{ 
				Gdi.iGridX = 0; 
				Gdi.iWidth1 = 0; 
				Gdi.iWidth2 = iWidthX; 
			} 
 
			if (nGridY > 0) 
			{ 
				Gdi.iGridY = iLoop; 
				Gdi.iHeight1 = iLoop * iHeightY; 
				Gdi.iHeight2 = iLoop * iHeightY + iHeightY; 
			} 
			else 
			{ 
				Gdi.iGridY = 0; 
				Gdi.iHeight1 = 0; 
				Gdi.iHeight2 = iHeightY; 
			} 
 
			Gdi.hMemDC = CreateCompatibleDC(hDDC); 
			Gdi.hDIBitmap = CreateCompatibleBitmap(hDDC,iWidthX,iHeightY); 
			SelectObject(Gdi.hMemDC,Gdi.hDIBitmap); 
			pGdiNode = Add_Gdi(pGdiNode,Gdi); 
		} 
	} 
	hNullDC = GetDC(NULL); 
} 
 
// 清除显示变量 
void ClearDisplay(HWND hWnd) 
{ 
	DeleteDC(hDDC); 
	DeleteDC(hNullDC); 
	Clear_Gdi(&GdiStart); 
} 
 
//得到区域的显示位图 
int GetRegionDisplay(HWND hWnd) 
{ 
	int		iWidth1,iWidth2,iHeight1,iHeight2; 
	BOOL	bGotBits; 
	DWORD	iLength; 
	char	*pStartDIB; 
 
	DWORD	dwLen1; 
	DWORD	dwBitMapHeader1; 
	char	*pDIBitmap1; 
	char	*pDIB1; 
	int		fChange1; 
	char	*pDIBChange1; 
 
	// 得到区域的矩形坐标 
	iWidth1 = pGdiNode->Gdi.iWidth1; 
	iWidth2 = pGdiNode->Gdi.iWidth2; 
	iHeight1 = pGdiNode->Gdi.iHeight1; 
	iHeight2 = pGdiNode->Gdi.iHeight2; 
 
	BitBlt(pGdiNode->Gdi.hMemDC,0,0,iWidth2,iHeight2,hDDC,iWidth1,iHeight1,SRCCOPY); 
 
	//将DDB转化成DIB 
	// 得到区域位图信息 
	GetObject(pGdiNode->Gdi.hDIBitmap,sizeof(BITMAP),&(pGdiNode->Gdi.DIBitmap)); 
	// 设置颜色模式 
	pGdiNode->Gdi.DIBitmap.bmBitsPixel = bmBitsPixel; 
	// 初始化位图信息头 
	pGdiNode->Gdi.BMIH.biSize = sizeof(BITMAPINFOHEADER); 
	pGdiNode->Gdi.BMIH.biWidth = pGdiNode->Gdi.DIBitmap.bmWidth; 
	pGdiNode->Gdi.BMIH.biHeight = pGdiNode->Gdi.DIBitmap.bmHeight; 
	pGdiNode->Gdi.BMIH.biPlanes = 1; 
	pGdiNode->Gdi.BMIH.biBitCount = (WORD)pGdiNode->Gdi.DIBitmap.bmPlanes * (WORD)pGdiNode->Gdi.DIBitmap.bmBitsPixel; 
	pGdiNode->Gdi.BMIH.biCompression = BI_RGB; 
	pGdiNode->Gdi.BMIH.biSizeImage = 0; 
	pGdiNode->Gdi.BMIH.biXPelsPerMeter = 0; 
	pGdiNode->Gdi.BMIH.biYPelsPerMeter = 0; 
	pGdiNode->Gdi.BMIH.biClrUsed = 0; 
	pGdiNode->Gdi.BMIH.biClrImportant = 0; 
 
	//设置区域的颜色数 
	pGdiNode->Gdi.nColors = 1 << pGdiNode->Gdi.BMIH.biBitCount; 
	if (pGdiNode->Gdi.nColors > 256) 
		pGdiNode->Gdi.nColors = 0;  
	// 计算为位图信息头和彩色表分配内存所需的尺寸 
	pGdiNode->Gdi.dwLen = (DWORD)(sizeof(BITMAPINFOHEADER) + pGdiNode->Gdi.nColors * sizeof(RGBQUAD)); 
 
	if (!pGdiNode->Gdi.fDIBitmap) 
	{ 
		pGdiNode->Gdi.pDIB = (char *)malloc(pGdiNode->Gdi.dwLen); 
		pStartDIB = pGdiNode->Gdi.pDIB; 
	} 
 
	pGdiNode->Gdi.lpBMIH = (LPBMIH)pGdiNode->Gdi.pDIB; 
	*(pGdiNode->Gdi.lpBMIH) = pGdiNode->Gdi.BMIH; 
	GetDIBits(hNullDC,pGdiNode->Gdi.hDIBitmap,0L,(DWORD)pGdiNode->Gdi.BMIH.biHeight,(LPBYTE)NULL,(LPBITMAPINFO)pGdiNode->Gdi.lpBMIH,DIB_RGB_COLORS); 
 
	// 以计算的尺寸设置区域位图信息头 
	pGdiNode->Gdi.BMIH = *(pGdiNode->Gdi.lpBMIH); 
	// 保存位图信息头的大小 
	pGdiNode->Gdi.dwBitMapHeader = pGdiNode->Gdi.dwLen; 
	pGdiNode->Gdi.dwLen += (DWORD)(pGdiNode->Gdi.BMIH.biSizeImage); 
	if (!pGdiNode->Gdi.fDIBitmap) 
	{ 
		pGdiNode->Gdi.pDIB = pStartDIB; 
		pGdiNode->Gdi.pDIB = (char *)realloc(pGdiNode->Gdi.pDIB,pGdiNode->Gdi.dwLen); 
	} 
 
	pGdiNode->Gdi.lpBMIH = (LPBMIH)pGdiNode->Gdi.pDIB; 
	bGotBits = GetDIBits(hNullDC,pGdiNode->Gdi.hDIBitmap,0L,(DWORD)pGdiNode->Gdi.BMIH.biHeight,(LPBYTE)pGdiNode->Gdi.lpBMIH + (pGdiNode->Gdi.BMIH.biSize + pGdiNode->Gdi.nColors * sizeof(RGBQUAD)),(LPBITMAPINFO)pGdiNode->Gdi.lpBMIH,DIB_RGB_COLORS); 
 
	// 比较区域DIBS之前和之后的变化 
	if (pGdiNode->Gdi.fDIBitmap) 
	{ 
		dwLen1 = pGdiNode->Gdi.dwLen; 
		dwBitMapHeader1 = pGdiNode->Gdi.dwBitMapHeader; 
		pDIBitmap1 = pGdiNode->Gdi.pDIBitmap; 
		pDIB1 = pGdiNode->Gdi.pDIB; 
		fChange1 = pGdiNode->Gdi.fChange; 
 
		// 每次4个字节的比较两副位图,注意要跳过位图的头部 
		__asm 
		{ 
			MOV		ECX,dwLen1 
			SUB		ECX,dwBitMapHeader1 
			SHR		ECX,2  
			MOV		EDX,dwBitMapHeader1 
			MOV		ESI,pDIBitmap1 
			ADD		ESI,EDX 
			MOV		EDI,pDIB1 
			ADD		EDI,EDX 
			REP		CMPSD 
			JNZ		SetFlagRegion1 
			MOV		fChange1,FALSE 
			JMP		ExitRegion1 
			SetFlagRegion1: 
			MOV		fChange1,TRUE 
			ExitRegion1: 
		} 
 
		//设置变化状态 
		pGdiNode->Gdi.fChange = fChange1; 
		// 为两副区域DIB的差别建立一个新的DIB 
		if (pGdiNode->Gdi.fChange) 
		{ 
			DWORD		iZeros = 0; 
			iLength = (pGdiNode->Gdi.dwLen - pGdiNode->Gdi.dwBitMapHeader); 
			pGdiNode->Gdi.pDIBChange = pGdiNode->Gdi.pDIBChangeStart; 
			pDIBChange1 = pGdiNode->Gdi.pDIBChange; 
 
			__asm 
			{ 
				MOV		ECX,iLength  
				SHR		ECX,2  
				MOV		EDI,pDIBChange1 
				MOV		ESI,pDIB1 
				ADD		ESI,dwBitMapHeader1 
				MOV		EDX,pDIBitmap1 
				ADD		EDX,dwBitMapHeader1 
				SubtractRegion: 
				LODSD 
				SUB		EAX,[EDX] 
				ADD		EDX,4 
				STOSD 
				DEC		ECX 
				JNZ		SubtractRegion 
			} 
 
			//拷贝到全局区域的DIB 
			memblast(pGdiNode->Gdi.pDIBitmap,pGdiNode->Gdi.pDIB,pGdiNode->Gdi.dwLen); 
			// 设置压缩长度 
			pGdiNode->Gdi.dwCompress = pGdiNode->Gdi.dwLen - pGdiNode->Gdi.dwBitMapHeader; 
			// 设置数据的起始位 
			pGdiNode->Gdi.iStartPos = pGdiNode->Gdi.dwBitMapHeader; 
		} 
	} 
	else 
	{ 
		iLength = (pGdiNode->Gdi.dwLen); 
		pGdiNode->Gdi.pDIBitmap = (char *)malloc(iLength); 
		pGdiNode->Gdi.pDIBChange = (char *)malloc(iLength); 
		pGdiNode->Gdi.pDIBChangeStart = pGdiNode->Gdi.pDIBChange; 
		memblast(pGdiNode->Gdi.pDIBitmap,pGdiNode->Gdi.pDIB,pGdiNode->Gdi.dwLen); 
		memblast(pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.pDIB,pGdiNode->Gdi.dwLen); 
 
		// 不需要再分配内存 
		pGdiNode->Gdi.fDIBitmap = TRUE; 
		pGdiNode->Gdi.fChange = TRUE; 
 
		pGdiNode->Gdi.dwCompress = pGdiNode->Gdi.dwLen; 
		pGdiNode->Gdi.iStartPos = 0; 
	} 
 
	return pGdiNode->Gdi.fChange; 
} 
 
// 发送Resolution到客户端 
void SendResolution(SOCKET MySocket) 
{ 
	char	szMessage[81]; 
	DWORD	iSent,iRecv; 
 
	// 建立屏幕宽度 
	memset(szMessage,'\0',sizeof(szMessage)); 
	sprintf(szMessage,"%d",iWidth); 
	iSent = Transmit(MySocket,szMessage,strlen(szMessage)); 
 
	// 接收确认 
	memset(szMessage,'\0',sizeof(szMessage)); 
	iRecv = recv(MySocket,szMessage,81,0); 
	szMessage[iRecv] = '\0'; 
 
	// 建立屏幕的高度 
	memset(szMessage,'\0',sizeof(szMessage)); 
	sprintf(szMessage,"%d",iHeight); 
	iSent = Transmit(MySocket,szMessage,strlen(szMessage)); 
 
	// 接收确认 
	memset(szMessage,'\0',sizeof(szMessage)); 
	iRecv = recv(MySocket,szMessage,81,0); 
	szMessage[iRecv] = '\0'; 
} 
 
// 通过socket发送区域显示位图 
int SendRegionDisplay(HWND hWnd,SOCKET MySocket) 
{ 
	char	szMessage[81]; 
	DWORD	iSent,iRecv; 
	int		fSend = FALSE; 
	int		iUpdates; 
	WORD	wTreeSize; 
	DWORD	dwByteTree[768]; 
	DWORD	dwCodes[514]; 
	DWORD	dwCompLen,dwLastCompLen; 
	BOOL	fTransmit; 
	char	*pTempDIB; 
	DWORD	dwMinCompress; 
 
	// 指向GDI链表的起始位 
	iUpdates = 0; 
	pGdiNode = GdiStart.pNext; 
	while (pGdiNode) 
	{ 
		//为每个网格得到区域显示 
		fSend = GetRegionDisplay(hWnd); 
		// 计算需要发送的变化的显示区域的数目 
		if (fSend) 
			iUpdates++; 
		// 移动到下一个节点 
		pGdiNode = pGdiNode->pNext; 
	} 
 
	// 发送到客户端需要更新的显示区域的数目 
	memset(szMessage,'\0',sizeof(szMessage)); 
	sprintf(szMessage,"%d",iUpdates); 
	iSent = Transmit(MySocket,szMessage,strlen(szMessage)); 
	// 接收确认 
	memset(szMessage,'\0',sizeof(szMessage)); 
	iRecv = recv(MySocket,szMessage,81,0); 
	szMessage[iRecv] = '\0'; 
 
	if (iUpdates > 0) 
	{ 
		// 指向GDI链表的起始位 
		pGdiNode = GdiStart.pNext; 
		while (pGdiNode) 
		{ 
			// 如果桌面发生了变化,则发送DIB 
			if (pGdiNode->Gdi.fChange) 
			{ 
				int		iCompressions = 1; 
				//无压缩 
				if (iCompressionLevel == 0)  
				{ 
					pGdiNode->Gdi.pDIBCompress = (char *)malloc(pGdiNode->Gdi.dwCompress); 
					memblast(pGdiNode->Gdi.pDIBCompress,pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress); 
					dwSendLen = pGdiNode->Gdi.dwCompress; 
				} 
				if (iCompressionLevel == 10) // 单遍霍夫曼编码压缩 
				{ 
					pGdiNode->Gdi.pDIBCompress = (char *)malloc(pGdiNode->Gdi.dwCompress + 1536); 
					// 生成霍夫曼字节树字典 
					wTreeSize = HuffmanDictionary(pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress,&dwByteTree[0],&dwCodes[0]); 
					// 使用霍夫曼压缩方法压缩图片 
					dwSendLen = HuffmanCompress(pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress,wTreeSize,&dwByteTree[0],&dwCodes[0],pGdiNode->Gdi.pDIBCompress); 
				} 
				else if (iCompressionLevel == 11) // 多遍霍夫曼压缩编码 
				{ 
					dwMinCompress = pGdiNode->Gdi.dwCompress + 1536; 
					pGdiNode->Gdi.pDIBCompress = (char *)malloc(dwMinCompress); 
					pTempDIB = (char *)malloc(pGdiNode->Gdi.dwCompress); 
					memblast(pTempDIB,pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress); 
					iCompressions = 0; 
					dwCompLen = pGdiNode->Gdi.dwCompress; 
					dwLastCompLen = dwCompLen; 
					for (;;) 
					{ 
						// 生成霍夫曼字节树字典 
						wTreeSize = HuffmanDictionary(pTempDIB,pGdiNode->Gdi.dwCompress,&dwByteTree[0],&dwCodes[0]); 
						// 计算压缩长度 
						dwCompLen = HuffmanCountCompress(pTempDIB,dwCompLen,wTreeSize,&dwCodes[0]); 
						if (dwCompLen < dwMinCompress) 
						{ 
							dwSendLen = HuffmanCompress(pTempDIB,dwLastCompLen,wTreeSize,&dwByteTree[0],&dwCodes[0],pGdiNode->Gdi.pDIBCompress); 
							memblast(pTempDIB,pGdiNode->Gdi.pDIBCompress,dwSendLen); 
							dwMinCompress = dwSendLen; 
							dwLastCompLen = dwCompLen; 
							iCompressions++; 
						} 
						else 
							break; 
					} 
					free(pTempDIB); 
				} 
				else if (iCompressionLevel == 12) // Run Length编码 
				{ 
					//为最坏的情况分配压缩空间 
					pGdiNode->Gdi.pDIBCompress = (char *)malloc(pGdiNode->Gdi.dwCompress * 3 + 4); 
					// Run Length编码图象 
					dwSendLen = RunLengthEncode(pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress,pGdiNode->Gdi.pDIBCompress); 
				} 
				else if (iCompressionLevel == 13) // Run Length&Huffman编码 
				{ 
					pTempDIB = (char *)malloc(pGdiNode->Gdi.dwCompress * 3 + 4); 
					pGdiNode->Gdi.pDIBCompress = (char *)malloc(pGdiNode->Gdi.dwCompress * 3 + 4); 
					// Run Length 编码图象 
					dwCompLen = RunLengthEncode(pGdiNode->Gdi.pDIBChange,pGdiNode->Gdi.dwCompress,pTempDIB); 
					// 生成霍夫曼字节树的字典 
					wTreeSize = HuffmanDictionary(pTempDIB,dwCompLen,&dwByteTree[0],&dwCodes[0]); 
					// 使用霍夫曼压缩Run Lenght编码的图象 
					dwSendLen = HuffmanCompress(pTempDIB,dwCompLen,wTreeSize,&dwByteTree[0],&dwCodes[0],pGdiNode->Gdi.pDIBCompress); 
					// 释放临时的DIB 
					free(pTempDIB); 
				} 
 
				// 建立位图控制消息 
				memset(szMessage,'\0',sizeof(szMessage)); 
				sprintf(szMessage,"%d;%d;%d;%ld;%ld;%ld;", 
					iCompressions, 
					pGdiNode->Gdi.iGridX,pGdiNode->Gdi.iGridY, 
					pGdiNode->Gdi.iStartPos, 
					pGdiNode->Gdi.dwCompress,dwSendLen); 
				// 发送控制消息 
				iSent = Transmit(MySocket,szMessage,strlen(szMessage)); 
 
				// 接收确认 
				memset(szMessage,'\0',sizeof(szMessage)); 
				iRecv = recv(MySocket,szMessage,81,0); 
				szMessage[iRecv] = '\0'; 
 
				// 发送压缩的DIB 
				fTransmit = Transmit(MySocket,pGdiNode->Gdi.pDIBCompress,dwSendLen); 
				// 释放压缩的DIB 
				free(pGdiNode->Gdi.pDIBCompress); 
				// 接收确认 
				memset(szMessage,'\0',sizeof(szMessage)); 
				iRecv = recv(MySocket,szMessage,81,0); 
				szMessage[iRecv] = '\0'; 
			} 
			pGdiNode = pGdiNode->pNext; 
		} 
	} 
	return iUpdates; 
} 
 
//传输数据到客户端 
BOOL Transmit(SOCKET MySocket,char *pData,DWORD dwLength) 
{ 
	WSAOVERLAPPED	olSend; 
	WSAEVENT	gheventOlSock; 
	WSAEVENT	eventArray[2]; 
	WSABUF		buffSend; 
	DWORD		dwRet,dwNumBytes,dwFlags; 
	int			nWSAError; 
	char		szError[81]; 
 
	// 为发送完成创建一个信号事件 
	gheventOlSock = WSACreateEvent(); 
	eventArray[0] = gheventOlSock; 
 
	// 初始化重叠发送的结构 
	ZeroMemory(&olSend, sizeof(WSAOVERLAPPED)); 
	// 为发送重叠结构创建一个信号时间 
	olSend.hEvent= gheventOlSock; 
	buffSend.len = dwLength; 
	buffSend.buf = pData; 
	// 持续发送,直到dwSendLen个字节被发送完成 
	while (TRUE) 
	{ 
		if ((dwRet = WSASend(MySocket,&buffSend,1,&dwNumBytes,0,&olSend,NULL)) == SOCKET_ERROR) 
		{ 
			nWSAError= WSAGetLastError(); 
			if (nWSAError != ERROR_IO_PENDING) 
			{ 
				sprintf(szError,"WSASend failed with error %d\n",nWSAError); 
				MessageBox(NULL,szError,"Server",MB_OK); 
			} 
		} 
	 
		if (WSAWaitForMultipleEvents(1,eventArray,FALSE,WSA_INFINITE,FALSE) == WSA_WAIT_FAILED) 
		{ 
			sprintf(szError,"WSAWaitForMultipleEvents failed %d\n", WSAGetLastError()); 
			MessageBox(NULL,szError,"Server",MB_OK); 
		}  
		// 重置gheventOlSock 
		WSAResetEvent(eventArray[0]); 
		if (WSAGetOverlappedResult(MySocket,&olSend,&dwNumBytes,FALSE,&dwFlags) == FALSE) 
		{ 
			sprintf(szError,"WSAGetOverlappedResult failed with error %d\n", WSAGetLastError()); 
			MessageBox(NULL,szError,"Server",MB_OK); 
		} 
		buffSend.len -= dwNumBytes; 
		if (buffSend.len == 0)  
			break; 
		else  
			buffSend.buf += dwNumBytes; 
	} 
 
	// 关闭信号事件 
	WSACloseEvent(gheventOlSock); 
	return TRUE; 
} 
 
//返回本机安装的所有的有XP1_GUARANTEED_DELIVERY and XP1_GUARANTEED_ORDER标志的协议和协议链 
int SelectProtocols(DWORD dwSetFlags,DWORD dwNotSetFlags,LPWSAPROTOCOL_INFO lpProtocolBuffer,LPDWORD lpdwBufferLength,WSAPROTOCOL_INFO *pProtocol) 
{ 
	LPBYTE				pBuf; 
	LPWSAPROTOCOL_INFO	pInfo; 
	DWORD				dwNeededLen; 
	LPWSAPROTOCOL_INFO	pRetInfo; 
	DWORD				dwRetLen; 
	int					nCount; 
	int					nMatchCount; 
	int					nRet; 
 
	// 决定需要的缓冲区大小 
	dwNeededLen = 0; 
	nRet = WSAEnumProtocols(NULL, NULL, &dwNeededLen); 
	if (nRet == SOCKET_ERROR) 
	{ 
		if (WSAGetLastError() != WSAENOBUFS) 
			return SOCKET_ERROR; 
	} 
	// 分配大小 
	pBuf = malloc(dwNeededLen); 
	if (pBuf == NULL) 
	{ 
		WSASetLastError(WSAENOBUFS); 
		return SOCKET_ERROR; 
	} 
 
	nRet = WSAEnumProtocols(NULL,(LPWSAPROTOCOL_INFO)pBuf,&dwNeededLen); 
	if (nRet == SOCKET_ERROR) 
	{ 
		free(pBuf); 
		return SOCKET_ERROR; 
	} 
 
	#define REJECTSET(f) \ 
	    ((dwSetFlags & f) && !(pInfo->dwServiceFlags1 & f)) 
	#define REJECTNOTSET(f) \ 
	    ((dwNotSetFlags &f) && (pInfo->dwServiceFlags1 & f)) 
	#define REJECTEDBY(f) (REJECTSET(f) || REJECTNOTSET(f)) 
 
	pInfo = (LPWSAPROTOCOL_INFO)pBuf;	 
	pRetInfo = lpProtocolBuffer; 
	dwRetLen = 0; 
	nMatchCount = 0; 
	for(nCount = 0; nCount < nRet; nCount++) 
	{ 
		while(1) 
		{ 
			if (REJECTEDBY(XP1_CONNECTIONLESS)) 
				break; 
			if (REJECTEDBY(XP1_GUARANTEED_DELIVERY)) 
				break; 
			if (REJECTEDBY(XP1_GUARANTEED_ORDER)) 
				break; 
			if (REJECTEDBY(XP1_MESSAGE_ORIENTED)) 
				break; 
			if (REJECTEDBY(XP1_PSEUDO_STREAM)) 
				break; 
			if (REJECTEDBY(XP1_GRACEFUL_CLOSE)) 
				break; 
			if (REJECTEDBY(XP1_EXPEDITED_DATA)) 
				break; 
			if (REJECTEDBY(XP1_CONNECT_DATA)) 
				break; 
			if (REJECTEDBY(XP1_DISCONNECT_DATA)) 
				break; 
			if (REJECTEDBY(XP1_SUPPORT_BROADCAST))  
				break; 
			if (REJECTEDBY(XP1_SUPPORT_MULTIPOINT)) 
				break; 
			if (REJECTEDBY(XP1_MULTIPOINT_DATA_PLANE)) 
				break; 
			if (REJECTEDBY(XP1_QOS_SUPPORTED)) 
				break; 
			if (REJECTEDBY(XP1_UNI_SEND)) 
				break; 
			if (REJECTEDBY(XP1_UNI_RECV)) 
				break; 
			if (REJECTEDBY(XP1_IFS_HANDLES)) 
				break; 
			if (REJECTEDBY(XP1_PARTIAL_MESSAGE)) 
				break; 
 
			dwRetLen += sizeof(WSAPROTOCOL_INFO); 
 
			if (dwRetLen > *lpdwBufferLength) 
			{ 
				WSASetLastError(WSAENOBUFS); 
				*lpdwBufferLength = dwNeededLen; 
				free(pBuf); 
				return SOCKET_ERROR; 
			} 
			nMatchCount++; 
			// 拷贝协议到调用者的buffer里 
			memblast(pRetInfo,pInfo,sizeof(WSAPROTOCOL_INFO)); 
			if (strcmp(pInfo->szProtocol,"MSAFD Tcpip [TCP/IP]") == 0) 
				memblast(pProtocol,pInfo,sizeof(WSAPROTOCOL_INFO)); 
			pRetInfo++; 
			break; 
		} 
		pInfo++; 
	} 
	free(pBuf); 
	*lpdwBufferLength = dwRetLen; 
	return(nMatchCount); 
} 
 
void memblast(void* dest,void* src,DWORD count) 
{ 
	DWORD	iCount; 
 
	__asm 
	{ 
		MOV		ECX,count 
		SHR		ECX,2 
		SHL		ECX,2 
		MOV		iCount,ECX 
 
		MOV		ESI,src 
		MOV		EDI,dest 
		MOV		ECX,iCount 
		SHR		ECX,2	 
		REP		MOVSD	 
 
		MOV		ECX,count 
		MOV		EAX,iCount 
		SUB		ECX,EAX 
 
		JZ		Exit 
 
		MOV		ESI,src	 
		ADD		ESI,EAX	 
		MOV		EDI,dest	 
		ADD		EDI,EAX		 
		REP		MOVSB		 
		Exit: 
	} 
} 
/* 
int GetLocalHostName(char* sHostName)	//获得本地计算机名称 
{ 
	char szHostName[256]; 
	int nRetCode; 
	nRetCode=gethostname(szHostName,sizeof(szHostName)); 
	if(nRetCode!=0) 
	{ 
		//产生错误 
		strcpy(sHostName,"没有取得"); 
		return GetLastError(); 
	} 
	strcpy(sHostName,szHostName); 
	return 0; 
} 
int GetIpAddress(char *sHostName, BYTE *f0,BYTE *f1,BYTE *f2,BYTE *f3)//获得本地IP 
{ 
	struct hostent FAR * lpHostEnt=gethostbyname(sHostName); 
	if(lpHostEnt==NULL) 
	{ 
		//产生错误 
		f0=f1=f2=f3=0; 
		return GetLastError(); 
	} 
	//获取IP 
	if(lpHostEnt->h_addr_list[0]) 
	{ 
		struct in_addr inAddr; 
		memmove(&inAddr,lpHostEnt->h_addr_list[0],4); 
		*f0=inAddr.S_un.S_un_b.s_b1; 
		*f1=inAddr.S_un.S_un_b.s_b2; 
		*f2=inAddr.S_un.S_un_b.s_b3; 
		*f3=inAddr.S_un.S_un_b.s_b4; 
	} 
	return 0; 
} 
*/