版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
遠程控制軟件的設計與開發(fā)多企業(yè)和增值分銷商正在把遠程控制技術作為有效的技術支持工具,許多網絡管理員都采用這類軟件對局域網進行遠程管理。遠程管理軟件對于出差在外的商務人員用處非常大,這樣他們可以隨時提取自己家里計算機中的數據和資料。本文介紹的軟件用C++語言編寫而成,能通過一臺主機控制網絡上的一臺或多臺遠程主機的鍵盤。軟件采用了C/S模式,即客戶端/服務器端模式??蛻舳藢Ψ掌鞫诉M行監(jiān)控操作,服務器端接收客戶端傳輸的數據并進行分析和執(zhí)行。本文首先對遠程控制軟件的原理和WinSock技術作了介紹,最后闡述了如何利用WinSock控件與遠程計算機建立連接,實現控制按鍵的功能。論文總頁數:26頁TOC\o"1-5"\h\z\o"CurrentDocument"引言1\o"CurrentDocument"1.1課題背景1\o"CurrentDocument"1.2國內外研究現狀1\o"CurrentDocument"1.3本課題研究的意義1\o"CurrentDocument"1.4本課題的研究方法1\o"CurrentDocument"遠程控制概述2\o"CurrentDocument"2.1遠程控制概念2\o"CurrentDocument"2.2遠程控制與其他程序的區(qū)別2\o"CurrentDocument"2.2.1遠程控制與病毒的區(qū)別2\o"CurrentDocument"2.2.2遠程控制與黑客的區(qū)別2\o"CurrentDocument"2.2.3遠程控制與木馬的區(qū)別3\o"CurrentDocument"控制遠程按鍵的背景技術介紹3\o"CurrentDocument"3.1Winsocket的介紹3\o"CurrentDocument"Socket的基本概念3\o"CurrentDocument"Winsocket3\o"CurrentDocument"3.2客戶端/服務器(C/S)模式3\o"CurrentDocument"控制遠程按鍵程序的需求分析4\o"CurrentDocument"4.1控制遠程按鍵的需求分析4\o"CurrentDocument"4.2控制遠程按鍵的流程分析4\o"CurrentDocument"5遠程按鍵控制的實現5\o"CurrentDocument"5.1使用Winsocket建立控制端和被控制端連接5\o"CurrentDocument"5.1.1初始化Winsock5\o"CurrentDocument"5.1.2創(chuàng)建套接字6\o"CurrentDocument"5.1.3指定本地地址7\o"CurrentDocument"5.1.4建立套接字連接7\o"CurrentDocument"5.1.5監(jiān)聽連接9\o"CurrentDocument"5.1.6關閉套接字9\o"CurrentDocument"5.2按鍵事件處理9\o"CurrentDocument"5.2.1數據傳輸9\o"CurrentDocument"5.2.2模擬按鍵10\o"CurrentDocument"5.3具體代碼10引言1.1課題背景我們知道,通常企業(yè)內部或者IT公司的客戶技術支持部門都有技術支持業(yè)務,其任務是通過電話解答疑難問題,努力減少技術人員到現場服務或者讓用戶把設備送到支持中心進行維護。這種技術支持方式盡管被普遍采用,但效率不高而且大大增加了技術支持成本。通常,技術支持必須依賴技術人員和用戶之間的口頭交流來進行,這種交流既耗時又容易出錯。許多商業(yè)用戶對計算機知之甚少,然而當遇到問題時,他們必須向技術人員提供故障情報及相關操作。在嘗試解決問題時,技術人員可能指導用戶執(zhí)行一系列復雜的過程,而這些過程對用戶來說或許完全不熟悉;如果用戶不能正確的按要求操作,反而使問題惡化。此外,如果通過電話不能解決問題,那么技術人員親自到用戶現場解決問題之前,計算機將一自不能使用。遠程控制軟件能使技術人員直接操作遠程計算機,就像操作本地機器一樣,無須用戶介入,技術人員技能得到該機器的問題的第一手材料,從而加快了問題的解決。實際上,使用遠程控制工具的技術人員能夠做到解答疑難問題,安裝和配置軟件,把軟件下載到用戶計算機上,配置應用程序和系統軟件設置并可通過實際操作培訓用戶。1.2國內外研究現狀根據IDC統計,美國遠程控制軟件市場從1998年的6.77億美元發(fā)展到2002年的19億美元,年增長率達31.5%,是軟件技術支持消費中第3個增長最快的領域。國內的遠程控制軟件發(fā)展也比較樂觀,出現了許多優(yōu)秀的軟件,比如大家都比較熟悉的“冰河”,“灰鴿子”等。1.3本課題研究的意義遠程控制軟件已經使用很多年了,起初是為了讓pc用戶在離開辦公室的時候能訪問其臺式PC硬盤中的信息,甚至可以通過其臺式PC訪問企業(yè)網絡資源。今天,許多企業(yè)和增值分銷商正在把遠程控制能力作為有效的技術支持工具。許多網絡管理員都采用這類軟件對局域網進行管理或者在自己家更新自己網站的內容。這類軟件對于出差在外的商務人員用處非常大,這樣他們可以隨時提取自己家里計算機中的數據和資料。1.4本課題的研究方法本軟件用C++語言編寫,采用的是C/S結構,一個客戶端,一個服務器端。客戶端是控制端,服務器端是被控制端。主要功能就是通過本地計算機,控制遠程另一臺計算機的鍵盤。主要思路是先用Winsocket建立兩邊的連接,客戶端向服務器端發(fā)送鍵碼,服務器端得到鍵碼后模擬出按鍵事件。遠程控制概述2.1遠程控制概念對于遠程控制軟件的定義有很多種。我們認為,遠程控制指管理人員在異地通過計算機網絡(WAN),異地撥號或雙方都接入Internet等手段,連接目標計算機,通過本地計算機對遠程計算機進行管理和維護的行為。遠程控制軟件實際上是一種客戶機/服務器程序,服務器程序安放在被控制的計算機端,客戶機安裝在控制端。在客戶端和服務器端都安裝成功之后,客戶端在網絡上搜尋已經安裝了服務器的遠程計算機;然后,客戶端就發(fā)指令獲得服務器端的連接指令,兩臺PC建立起連接,就可以通過網絡的互連協議TCP/IP進行遠端控制。遠程控制的原理很簡單:在本機上直接啟動運行的程序,擁有與使用者(客戶端)相同的權限。因此如果能夠啟動服務器端的服務程序,就可以使用相應的客戶端程序直接控制主機了。也就是說客戶端就好比一個超級用戶,可以直接控制計算機。2.2遠程控制與其他程序的區(qū)別遠程控制軟件可以為我們的網絡管理工作做很多工作,以保證網絡和計算機操作系統的安全。這類程序的監(jiān)聽功能,也是為了保證網絡的安全而設計的,但是如果使用不當的話,就會出現很多的問題。為了達到遠程控制的目的,就必須將這些軟件隱蔽起來。例如有的遠程控制軟件為了不讓用戶發(fā)現而被刪除,就采用了一些辦法讓自己隱蔽起來,使遠程控制程序本身附著在某些Windows程序上,以增強駐留系統的可靠性。然而,正是由于這種功能,才使遠程控制軟件變得可怕起來,也使遠程控制軟件,病毒和黑客程序之間的區(qū)別變得越來越模糊。2.2.1遠程控制與病毒的區(qū)別計算機病毒是能通過某種途徑潛伏在計算機存儲介質(或程序)里,當達到某種條件時即被激活的具有對計算機資源進行破壞作用的一種程序或指令集合。計算機病毒一般具有破壞性,隱蔽性,潛伏性,傳染性等特點。從計算機病毒的定義和特征中可以看出,遠程控制軟件與病毒的區(qū)別是十分明顯的。最基本的區(qū)別就在于病毒有很強的傳染性,而遠程控制軟件沒有。但是,如果遠程控制軟件沒有好的處理好軟件的安全問題,就會跟病毒相差無幾了。2.2.2遠程控制與黑客的區(qū)別“黑客”一詞來源于英語單詞hack,本指“手法巧妙,技術高明的惡作劇”。今天,在最新和最普遍的意思上說,“黑客”意味著那些偷偷地,未經許可就進入別人計算機系統的計算機犯罪。他們或修改網頁搞惡作劇或散布流言進行恐嚇,或破壞系統程度,施放病毒使系統險入癱瘓,或竊取政治,軍事與商業(yè)機密,或進行電子郵件騷擾,或轉移資金帳戶,竊取錢財,真所謂作案方式多樣,花樣翻新,令人防不勝防。由此可見,遠程控制與黑客的區(qū)別是較大的。黑客往往利用操作系統和網絡的漏洞進行破壞活動,而遠程控制軟件的一大任務就是要保護控制端計算機,使之不受非授權用戶的訪問。當然,如果編寫遠程控制軟件的唯一目的就是為了盜竊人家計算機上的隱私,這樣的遠程控制軟件就不再是有用的軟件而是惡性的黑客程序了。2.2.3遠程控制與木馬的區(qū)別木馬是一種在遠程計算機之間建立起連接,使遠程計算機能夠通過網絡控制本地計算機的程序。它的運行遵循TCP/IP協議。由于它像間諜一樣潛入用戶的電腦,為其他人的攻擊打開后門,與戰(zhàn)爭的“木馬”戰(zhàn)術十分相識,因而得名木馬程序。木馬與遠程控制軟件的最大區(qū)別就是木馬具有隱蔽性而遠程控制軟件沒有。控制遠程按鍵的背景技術介紹3.1Winsocket的介紹Socket的基本概念實際上,Socket在計算機中提供了一個通信端口(套接口)。通過這個端口,一臺計算機可以與任何一臺具有Socket接口的計算機通信。通信的基礎是套接口,一個套接口是通信的一端,在這一端上可以找到與其對應的一個名字。一個正在被使用的套接口都有他的類型和與其相關的進程,套接口存在于通信域中。一個套接口通常和同一個域中的套接口交換數據(數據交換也可以穿越域的界限,但這時一定要執(zhí)行某種解釋程序)。應用程序在網絡上傳輸,接收的信息都通過這個套接口來實現。在應用開發(fā)中就像使用文件句柄一樣,可以對Socket句柄進行讀寫操作。WinsocketwindowsSocket(WinSock)API是基于BSD版本的套接字,但只為Windows進行了專門的擴展。此外,WinSock2.0能支持許多網絡協議,包括TCP/IP,DECNet和Novell的IPX/SPX等°Windows套接字規(guī)范是一個由幾家開發(fā)商支持的接口規(guī)范。每個開發(fā)商都提供了他們自己的DLL來和傳輸棧一起工作。3.2客戶端/服務器(C/S)模式在TCP/IP網絡應用中,通信的兩個進程間相互作用的主要模式是客戶機/服務器模式(Client/Server)。即客戶向服務器發(fā)出服務請求,服務器接收到請求后,提供相應的服務??蛻魴C/服務器模式的建立基于以下兩點:首先,建立網絡的起因是網絡中軟硬件資源,運算能力和信息不均等,需要共享,從而造就擁有眾多資源的主機提供服務,資源較少的客戶請求服務這一非對等作用;其次,網間進程通信完全是異步的,相互通信的進程見既不存在父子關系,又不共享內存緩沖區(qū),因此需要一種機制為希望通信的進程間建立聯系,為兩者的數據交換提供同步,這就是基于客戶機/服務器模式的TCP/IP??刂七h程按鍵程序的需求分析4.1控制遠程按鍵的需求分析本程序的主要作用是控制服務器端的按鍵。當客戶端發(fā)生鍵盤按鍵事件時,服務器端能夠得到鍵碼,實現按鍵的模擬。主要由以下幾部分構成:(1)實現使用WinSocket建立客戶端和服務器端連接。要想實現遠程控制,首先就要實現遠程的互連。用WinSocket將客戶端和服務器端連接起來后,服務器端才可以得到控制端的信息。(2)控制端發(fā)送鍵碼。當客戶端與服務器端連接好以后,客戶端要想控制服務器端的按鍵,必須要向服務器端發(fā)送與鍵盤按鍵對應的鍵碼,服務器端得到了這個鍵碼后才可以做出按鍵的模擬。(3)實現服務器端模擬按鍵事件。服務器端在得到客戶端傳來的鍵碼后,根據鍵碼做出正確的按鍵模擬,實現控制遠程按鍵的功能。4.2控制遠程按鍵的流程分析客戶端服務端圖1控制遠程按鍵流程分析圖
5遠程按鍵控制的實現5.1使用Winsocket建立控制端和被控制端連接首先,客戶端和服務器端都要創(chuàng)建一個數據套接字。接著,服務器調用bind()函數給套接字分配一個公認的端口。這樣,客戶端和服務器端就使用同樣的端口來表示服務器套接字。一旦服務器將公認端口分配給了套接字,客戶端和服務器端就都能使用sendto()和recvfrom()來發(fā)送和接收數據報直到完成傳遞。然后調用closesocket來關閉套接字。5.1.1初始化WinsockWSAStartup()函數的原型聲明如下:IntWSAStartup(WORDwVersionRequested,LPWSADATAlpWSAData);該函數共有兩個參數。一個參數是一個WORD(雙字節(jié))型數值,他指應用程序中要使用的WinSock規(guī)范的最高版本。其中主版本在低位字節(jié),副版本號在高位字節(jié)。第二個參數指一個指向WSDATA結構的指針,該結構的定義如下:TypedefstructWSAData{WORDWORDCharCharUnsignedshortWORDWORDCharCharUnsignedshortUnsignedshortCharFAR*wVersion;wHighVersion;szDescription[WSADESCRIPTION_LEN+1];szSyestemStatus[WSASYS_STATUS_LEN+1];iMaxSocket;iMaxUdpDg;IpVendorInfo;}WSADATA,FAR*LPWSADJTA其中成員wVersion指WindowsSockets的版本號。成員wHighVersion指WindowsSockets的最高版本。通常情況下,該成員的取值與成員wVersion相同。成員szDescrpition指WindowsSockets實現的句柄字符串。成員szSystemStatus指WindowsSockets的配置信息或相關狀態(tài)。成員iMaxSockets,iMaxUdpDg和lpVendorInfo保留;在WindowsSocket2及以后的版本中被忽略。我們一般采用如下代碼來調用WSAStartup():#include<winsocket.h>//對應winSock2,應該包含winsock2.hWSADATAWSAData;If(WSAStartup(0x0101,&WSAData)){〃初始化winSock時發(fā)生錯誤MessageBox(“不能加載windows套接字動態(tài)連接庫”,"遠程控制”,MB_OK);Return;}if(WSAData.wVersion!=0x0101){〃支持版本無效,報告后終止return;}這時,如果WinSock.dll或底層網絡子系統沒有正確初始化或沒有找到,WSAtartup()將返回WSASYSNOTREADY。此外,這個函數允許應用程序協商使用某種版本的WinSock規(guī)范。通常在調用WSAStarup()時,我們應該指定想使用的WinSock最高版本。如果這個版本比任何DLL支持的版本低,WSAStartup()將返回WSAVERNOTSUPPORTEDo如果我們要求的版本高于或等于DLL(動態(tài)鏈接庫)所支持的版本。WSAData的wVersion成員將包含應用程序應該使用的版本。而wHighVersion成員中將包含DLL所支持的最高版本號。如果返回到wVersion成員的版本號不能被應用程序所接受,我們就應該調用WSACleanup()并退出引用程序,或找一個不同的WinSock32.DLL來試一試。當然,這時需要動態(tài)加載新的DLL,并從中調用WSAStartup()。5.1.2創(chuàng)建套接字任何應用程序在使用套接字之前,首先必須擁有一個套接字,系統調用
socket函數向應用程序提供創(chuàng)建套接字的手段。Socket()函數的原型聲明如下:SOCKETPASCALFARsocket(intaf,inttype,intprotocol);該函數共有3參數,其中參數af指定通信發(fā)生的區(qū)域。UNIX系統支持的地址簇有AF_UNIX,AF_INET,AF_NS等。而DOS,Windows中僅支持AF_INET,它是網際網區(qū)域。
參數type描述建立的套接字類型。也就是指流式套接字還是數據報套接字。參數protocol說明該套接字使用的特定協議,如果該參數設為0。則表示使用默認的連接模式。Socket()函數根據這3個參數建立一個套接字,并將相應的資源分配給它,同時返回一個整型套接字句柄。5.1.3指定本地地址當一個套接字用socket()創(chuàng)建后,存在一個名字空間(地址簇),但它沒有被命名。Bind()將套接字地址(包括本地主機地址和本地端口地址)與所創(chuàng)建的套接字編號聯系起來,即將名字賦予套接字°bind()函數的原型聲明如下:intPASCALFARbind(SOCKERs,conststructsockaddrFAR*name,intnamelen);bind()函數共有3個參數,其中參數s是由socket()函數調用返回的并且未作連接的套接字句柄。參數name是賦給套接字s的本地地址(名字),其長度可變,結構隨通信域的不同而不同。參數namelen指參數name的長度。如果調用成功,bind()函數返回0;否則,返回SOCKER_ERROR。地址在建立套接字通信過程中起著重要作用,作為一個網絡應用程序設計者對套接字地址結構必須有明確的認識。例如,UNIXBSD有一組描述套接字地址的數據結構,其中使用TCP/IP協議的地址結構為:structsockaddr_in(/*AF_INET*//*16位端口號,網絡字節(jié)順/*32位/*AF_INET*//*16位端口號,網絡字節(jié)順/*32位IP地址,網絡字節(jié)順/*保留*/序*/structin_addrsin_addr序*/charsin_zero[8];}5.1.4建立套接字連接建立套接字連接需要使用兩個函數。即connect()與accept()。這兩個函數用于完成一個完整相關的建立,其中connect()用于建立連接。無連接的套接字進程也可以調用connect。,但這時在進程之間沒有實際的報文交換,調用將從本地操作系統直接返回。這樣做的優(yōu)點是程序員不必為每一數據指定目的地址,而且如果收到一個數據報,其目的端口未與任何套接字建立“連接”,便能判斷該端口不可操作。Accept()用于使服務器等待來自某客戶進程的實際連接。Connect。函數的原型聲明如下:intPASCALFARconnect(SOCKERs,conststructsockaddrFAR*name,intnamelen);Connect()函數共有3個參數,其中參數s指要建立連接的本地套接字句柄。參數name指對方套接字地址結構的指針,對方套接字地址長度由參數namelen說明。如果調用成功,connect()函數返回0;否則,返回SOCKET_ERROR。在面向連接的協議中,該函數調用導致本地系統和外部系統之間連接的實際建立。由于地址簇總被包含在套接字地址結構的前兩個字節(jié)中,并通過socket()函數調用某個協議簇相關。因此bind()和connect()不需要協議作為參數。Accept()函數的原型聲明如下:SOCKETPASCALFARaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);該函數也有3個參數,其中參數s為本地套接字句柄,在用做accept()函數調用的參數前應該先調用listen()。參數addr是指向客戶方套接字地址結構的指針,用來接收連接實體的地址。Addr的確切格式由套接字創(chuàng)建時建立的地址簇決定。參數addlen為客戶方套接字地址的長度(字節(jié)數)。如果調用成功,accept()函數返回一個SOCKET類型的值,表示接收到的套接字的句柄;否則,返回INVALID_SOCKET。Accept()用于面向連接的服務。參數addr和addrlen存放客戶方的地址信息。調用前,參數addr指向一個初值為空的地址結構,而addrlen的初始值為0;調用accepet()函數后,服務器等待從編號為s的套接字上接受客戶連接的請求,而連接請求是由客戶方的connect()調用發(fā)出的。當有連接請求到達時,accept()調用將請求連接隊列上的第一個客戶方套接字地址及長度放入addr和addrlen,并創(chuàng)建一個與s有相同性質的新套接字號。新的套接字可用于處理服務器并發(fā)請求。Socket(),bind(),connect(),accept()這4個套接字系統調用可以完成一個完整五元通信(協議,本地主機地址和端口號,目的地址和端口號)相關的建立。Socket()指定五元組中的協議元,它的用法與是否為客戶機或服務器,是否面向連接無關。Bind()指定五元中的本地二元,即本地主機地址和端口號,其用法與是否面向連接有關;在服務器方無論是否面向連接,均要調用bind();在客戶方,若采用面向連接,則可以不調用bind(),而通過connect()自動完成。若采用無連接,客戶方必須使用bind()以獲得一個唯一的地址。5.1.5監(jiān)聽連接建立連接之后,服務端套接字要調用listen()函數,此調用用于面向連接服務器,表明它愿意接收連接。Listen()需在accept()之前調用,listen()函數的原型聲明如下:intPASCALFARlisten(SOCKETs,intbacklog);該函數共有兩個參數,其中參數s標識一個本地已建立但尚未連接的套接字句柄,服務器愿意從它上面接受請求。參數backlog表示請求連接隊列的最大長度,用于限制排隊請求的個數。目前允許的最大值為5。如果調用成功,listen()函數返回零;否則,返回SOCKET_ERROR。Listen()在執(zhí)行調用過程中可為沒有調用過bind()的套接字s完成所必需的連接,并建立長度為backlog的請求連接隊列。調用listen()是服務器接收一個連接請求的4個步驟中的第3步。它在調用socket(),分配一個流套接字且調用bind()給s賦予一個名字之后調用,而且一定要在accept()之前調用。5.1.6關閉套接字closesocket()關閉套接字s,并釋放分配給該套接字的資源;如果s涉及一個打開的TCP連接。則該連接被釋放。Closesocket()函數的原型聲明如下:BOOLPASCALFARclosesocket(sockers);該函數只有一個參數s,它指待關閉的套接字句柄。如果調用成功,closesoker()返回零;否則,返回SOCKET_ERROR。5.2按鍵事件處理5.2.1數據傳輸當一個連接建立好以后,就可以傳輸數據了,常用的函數調用有send()和recv()。Send()調用用于在參數s指定的已連接的數據報或流套接字上發(fā)送輸出數據,其原型聲明如下:IntPASCALFARsend(SOCKETs,constcharFAR*buf,intlen,intflags);該函數也有4個參數,其中參數s為已連接的套接字句柄。參數buf指向接收輸入數據緩沖區(qū)的指針,其長度由len指定。參數flags指定傳輸控制方式,如是否接收帶外數據等。如果調用成功,recv()函數返回總共接收的字節(jié)數;如果連接被關閉,返回零。否則,返回SOCKETERRORo為了從套接字中接受數據,可以使用recv()函數。其函數原型聲明如下:intrecv(SOCKETs,charFAR*buf,intlen,intfalgs):recv()函數有4個參數,其中參數s指套接字句柄。參數buf和len分別指將要接收數據的緩沖區(qū)及緩沖區(qū)長度。參數flags可被設置成MSG-OOB,用來接收帶外數據,或設置成MSG-PEEK用來向緩沖區(qū)填入收到的數據,而且仍按照數據的輸入順序進行填充。對套接字來說,如果數據是按輸入的隊列接收過來的,recv()函數將返回讀入數據的字節(jié)數,否則,recv()將返回SOCKET—ERRORo5.2.2模擬按鍵函數keybd_event()綜合一個按鍵事件,系統用這個事件產生WM_KEYUP或WM_KEYDOWN消息.在WindowsNT下,該函數被SendInput()所代替.函數keybd_event()的原型如下:VOIDkeybd_event(BYTEbVk,BYTEbScan,DWORDdwFlags,DWORDdwExtraInfo);函數keybd_event()有4個參數,其中參數bVk指所按鍵的虛擬鍵值.取值范圍在1至254之間。常見的特殊鍵值有:Tab(9),Shift(16),Ctrl(17),Alt(18),CapsLock(20),Esc(27),Win(91,92),NumLock(144)及ScrollLock(145)等.參數bScan指所按鍵的掃描碼。參數dwFlags指函數操作標志位集合,應用程序可以檢測這個值。它可以取以下值。KEYEVENTF_EXTENDEDKEY:如果指定該值,則鍵盤掃描碼加一個前綴(224)。KEYEVENTF_KEYUP:如果指定該值,則鍵釋放,否則,鍵一直被按下。參數dwExtralnfo指向一個附加的與鍵值有關聯的32位值。5.3具體代碼由于篇幅有限,這里只列出了部分重要代碼。服務器端套接字的創(chuàng)建,綁定,連接:charchName[256];sockaddr_inaddr;hostent*pEnt=NULL;intaddrlen=0,nRet=0;nRet=::gethostname(chName,256);m_sckServer=socket(AF_INET,SOCK_STREAM,0);if(m_sckServer!=INVALID_SOCKET){pEnt=::gethostbyname(chName);if(pEnt){addr.sin_family=AF_INET;addr.sin_port=htons(m_uPort);addr.sin_addr.s_addr=INADDR_ANY;nRet=::bind(m_sckServer,(sockaddr*)&addr,sizeof(addr));if(nRet!=SOCKET_ERROR){nRet=::listen(m_sckServer,SOMAXCONN);if(nRet!=SOCKET_ERROR){addrlen=sizeof(addr);TRACE(_T("開始了服務,等待客戶......\n"));m_sckClient[0]=::accept(m_sckServer,(sockaddr*)&addr,&addrlen);if(m_sckClient[0]!=INVALID_SOCKET){〃為了同步::PL_SendSocketData(m_sckClient[0],NULL,0,PL_TEMP,MSG_OOB);}m_sckClient[1]=::accept(m_sckServer,(sockaddr*)&addr,&addrlen);if(m_sckClient[0]!=INVALID_SOCKET&&m_sckClient[1]!=INVALID_SOCKET)TRACE(_T("客戶連接上了.......\n"));服務器端關閉套接字:BOOLCSocketThread::ExitServer(){TRACE(_T("退出服務,重新等待連接......\n"));if(g_pSendDIBThread!=NULL){::TerminateThread(g_pSendDIBThread->m_hThread,0);::WaitForSingleObject(g_pSendDIBThread->m_hThread,INFINITE);g_pSendDIBThread=NULL;}if(g_pWaitCommandThread!=NULL){::TerminateThread(g_pWaitCommandThread->m_hThread,0);::WaitForSingleObject(g_pWaitCommandThread->m_hThread,INFINITE);g_pWaitCommandThread=NULL;}if(m_sckClient[0]!=INVALID_SOCKET){::closesocket(m_sckClient[0]);}if(m_sckClient[1]!=INVALID_SOCKET){::closesocket(m_sckClient[1]);}if(m_sckServer!=INVALID_SOCKET){::closesocket(m_sckServer);}m_sckClient[0]=INVALID_SOCKET;m_sckClient[1]=INVALID_SOCKET;m_sckServer=INVALID_SOCKET;returnTRUE;}服務器端接收客戶端發(fā)送的指令:intWINAPIPL_ReadSocketData(SOCKETs,BYTE*chData,intnLen,BYTE*chFlag,UINTuFlag){intnRet=INVALID_SOCKET;if(s!=INVALID_SOCKET){nRet=::recv(s,(char*)chData,nLen,uFlag);if(nRet>0){if(chFlag!=NULL){*chFlag=chData[0];}}}returnnRet;}服務器端處理指令:intCSocketThread::Run(){g_pSendInfoThread=AfxBeginThread(SendInfoThread,NULL,THREAD_PRIORITY_IDLE);while(1){if(CreateServer()){BYTE*chData=newBYTE[PL_SOCKET_MAXBYTES+1];while(1){I/WdEAXBY::"5PL_SOCKET_MAXBYTES,NULL);if(nRet!=SOCKET_ERROR)//處理命令nRet=DoReceive(chData,nRet);}else{TRACE(_T("接收數據錯誤,客戶已經斷開了......\n"));break;}}delete[]chData;chData=NULL;}ExitServer();}returnExitInstance();}intCSocketThread::DoReceive(BYTE*chData,intnLen){intnRet=0;switch(chData[0])//第一個字符為命令{casePL_PEEPER_VER://取服務端版本{charchTemp[15];ZeroMemory(chTemp,15);sprintf(chTemp,"%s",PEEPER_SERVER_VER_15);::PL_SendSocketData(m_sckClient[0],(BYTE*)chTemp,strlen(chTemp),PL_PEEPER_VER);}break;casePL_CLOSE_PEEPER://關閉服務,退出程序{ExitServer();ExitThread(0);}break;casePL_CLIENT_CLOSE://關閉連接{ExitServer();}break;casePL_MSG://顯示一個對話框信息,使用了線程{g_strAString.Format(_T("%s"),chData+1);if(g_pWaitCommandThread!=NULL){::TerminateThread(g_pWaitCommandThread->m_hThread,0);::WaitForSingleObject(g_pWaitCommandThread->m_hThread,INFINITE);g_pWaitCommandThread=NULL;}g_pWaitCommandThread=AfxBeginThread(WaitCommandThread,(LPVOID)PL_MSG);}break;/以下是模擬按鍵。casePL_KEY_DOWN://一個鍵被按下{UINTuChar=*((UINT*)(chData+1));UINTuFlag=*((UINT*)(chData+sizeof(UINT)+1));::PL_KeyDown(uChar,uFlag);::PL_SendSocketData(m_sckClient[0],NULL,0,PL_TEMP);}break;casePL_KEY_UP://一個鍵被彈起{UINTuChar=*((UINT*)(chData+1));UINTuFlag=*((UINT*)(chData+sizeof(UINT)+1));::PL_KeyUp(uChar,uFlag);::PL_SendSocketData(m_sckClient[0],NULL,0,PL_TEMP);}break;客戶端端初始化套接字:BOOLWINAPIPL_InitSocket(){#defineMAJOR_VERSION1#defineMINOR_VERSION2intnStatus=0;WORDwMajorVersion=MAJOR_VERSION;WORDwMinorVersion=MINOR_VERSION;WORDwVersionReqd=MAKEWORD(wMajorVersion,wMinorVersion);WSADATAlpmyWSAData;nStatus=::WSAStartup(wVersionReqd,&lpmyWSAData);if(nStatus!=0){returnFALSE;}客戶端連接服務器:intnRet=0;sockaddr_inaddr;hostent*pEnt=NULL;〃套接字的創(chuàng)建。m_pPeeperWnd->m_sckClient[0]=::socket(AF_INET,SOCK_STREAM,0);m_pPeeperWnd->m_sckClient[1]=::socket(AF_INET,SOCK_STREAM,0);TRACE(_T("ClientSocket0and1:%d,%d.\n"),m_pPeeperWnd->m_sckClient[0],m_pPeeperWnd->m_sckClient[1]);if(m_pPeeperWnd->m_sckClient[0]==INVALID_SOCKET||m_pPeeperWnd->m_sckClient[1]==INVALID_SOCKET){bRet=FALSE;break;}〃為套接字分配地址。pEnt=::gethostbyname(m_pPeeperWnd->m_strIP);if(!pEnt){bRet=FALSE;break;}addr.sin_family=AF_INET;addr.sin_port=::htons((u_short)(m_pPeeperWnd->m_uPort));addr.sin_addr.S_un.S_un_b.s_b1=pEnt->h_addr_list[0][0];addr.sin_addr.S_un.S_un_b.s_b2=pEnt->h_addr_list[0][1];addr.sin_addr.S_un.S_un_b.s_b3=pEnt->h_addr_list[0][2];addr.sin_addr.S_un.S_un_b.s_b4=pEnt->h_addr_list[0][3];bRet=FALSE;//defaultfor(inti=0;i<3;i++){intnRet1=::connect(m_pPeeperWnd->m_sckClient[0],(sockaddr*)&addr,sizeof(addr));if(nRet1!=SOCKET_ERROR){BYTEchData[5];ZeroMemory(chData,5);::PL_ReadSocketData(m_pPeeperWnd->m_sckClient[0],chData,5,NULL);}else{TRACE(_T("SocketErrorCode=%d.\n"),::WSAGetLastError());TRACE(_T("Client[0]is:%s.\n"),(nRetl==0)?_T("Ok"):_T("Failed."));intnRet2=::connect(m_pPeeperWnd->m_sckClient[1],(sockaddr*)&addr,sizeof(addr));if(nRet2==SOCKET_ERROR){TRACE(_T("SocketErrorCode=%d.\n"),::WSAGetLastError());}TRACE(_T("Client[1]is:%s.\n"),(nRet2==0)?_T(”O(jiān)k”):_T(”Failed”));if(nRet1==SOCKET_ERROR||nRet2==SOCKET_ERROR){Sleep(2000);continue;}charchConnectInfo[512];ZeroMemory(chConnectInfo,512);intnRet=::PL_ReadSocketData(m_pPeeperWnd->m_sckClient[0],(BYTE*)chConnectInfo,512,NULL);m_pPeeperWnd->SetConnectInfo(chConnectInfo);bRet=TRUE;//ConnectOk!break;}關閉連接:BOOLCPeeperWnd::ExitConnect(){if(m_sckClient[0]!=INVALID_SOCKET){::PL_SendSocketData(m_sckClient[0],NULL,0,PL_CLIENT_CLOSE);::closesocket(m_sckClient[0]);}if(m_sckClient[1]!=INVALID_SOCKET)::closesocket(m_sckClient[1]);}m_sckClient[0]=INVALID_SOCKET;m_sckClient[1]=INVALID_SOCKET;if(m_pNotifyWnd){::PostMessage(m_pNotifyWnd->GetSafeHwnd(),PL_PEEPER_NOTIFY(WPARAM)PL_PEEPER_NOTIFY_DISCONNECT,(LPARAM)this);}returnTRUE;}截取鍵碼:這個功能是在窗口中實現的,所以沒有使用SetWindowsHookex。voidCPeeperWnd::OnKeyDown(UINTnChar,UINTnRepCnt,UINTnFlags){if(CanSend()&&(((BYTE)nChar!=VK_LWIN&&(BYTE)nChar!=VK_RWIN))&&GetEnableFlag(PL_ENABLE_KEY)){BYTEchTemp[15];ZeroMemory(chTemp,15);memcpy(chTemp,&nChar,sizeof(UINT));memcpy(chTemp+sizeof(UINT),&nFlags,sizeof(UINT));intnRet=::PL_SendSocketData(m_sckClient[0],chTemp,sizeof(int)*2,PL_KEY_DOWN);if(nRet<=0){ExitConnect();return;}nRet=::PL_ReadSocketData(m_sckClient[0],chTemp,2,NULL);return}CScrollView::OnKeyDown(nChar,nRepCnt,nFlags);}voidCPeeperWnd::OnKeyUp(UINTnChar,UINTnRepCnt,UINTnFlags){if(CanSend()&&(((BYTE)nChar!=VK_LWIN&&(BYTE)nChar!=VK_RWIN))&&GetEnableFlag(PL_ENABLE_KEY)){BYTEchTemp[15];ZeroMemory(chTemp,15);memcpy(chTemp,&nChar,sizeof(UINT));memcpy(chTemp+sizeof(UINT),&nFlags,sizeof(UINT));intnRet=::PL_SendSocketData(m_sckClient[0],chTemp,sizeof(int)*2,PL_KEY_UP);if(nRet<=0){ExitConnect();return;}nRet=::PL_ReadSocketData(m_sckClient[0],chTemp,2,NULL);return;}CScrollView::OnKeyUp(nChar,nRepCnt,nFlags);}oidCPeeperWnd::OnSysKeyDown(UINTnChar,UINTnRepCnt,UINTnFlag
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年浙科版必修2物理下冊階段測試試卷含答案
- 2025年新科版七年級生物下冊階段測試試卷含答案
- 2025年滬科版選修化學下冊階段測試試卷含答案
- 2025年滬科版必修1歷史上冊階段測試試卷含答案
- 2025年粵教版必修2歷史下冊階段測試試卷含答案
- 2025年冀教版九年級歷史下冊月考試卷含答案
- 2025年滬教版七年級歷史下冊月考試卷含答案
- 2025年粵教滬科版九年級歷史下冊階段測試試卷
- 2025年湘教版八年級歷史上冊階段測試試卷含答案
- 二零二五年度文化展覽場地租賃合同協議書4篇
- 衛(wèi)生服務個人基本信息表
- 醫(yī)學脂質的構成功能及分析專題課件
- 高技能人才培養(yǎng)的策略創(chuàng)新與實踐路徑
- 廣東省湛江市廉江市2023-2024學年八年級上學期期末考試數學試卷(含答案)
- 2024年湖北省知名中小學教聯體聯盟中考語文一模試卷
- 安徽省蕪湖市2023-2024學年高一上學期期末考試 生物 含解析
- 燃氣行業(yè)有限空間作業(yè)安全管理制度
- 《地下建筑結構》第二版(朱合華)中文(2)課件
- JB T 7946.1-2017鑄造鋁合金金相
- 包裝過程質量控制
- 通用電子嘉賓禮薄
評論
0/150
提交評論