• 基于visual c++之windows核心编程代码分析(49)基于匿名管道实现远程控制


     匿名管道是一种未命名的、单向管道,通常用来在一个父进程和一个子进程之间传输数据。匿名的管道只能实现本地机器上两个进程间的通信,而不能实现跨网络的通信。

    匿名管道
         匿名管道是一种未命名的、单向管道。通常用来在父进程和子进程之间传输数据。匿名管道总是本地的,不能在网络之间传递数据。
    匿名管道操作
        CreatePipe函数创建一个匿名管道,并且返回两个句柄:一个读管道的句柄和一个写管道的句柄。读句柄具有管道的只读权限,写句柄具有管道的只写权 限。为了利用管道交换数据,管道服务端必须把管道句柄传给另一个进程。通常情况下,这是通过继承实现的(参见1.1.2);就是说,父进程允许子进程继承 这个句柄。进程也可以使用DuplicateHandle函数复制一个管道句柄,再通过一些进程间通信机制,比如DDE或者共享内存,把它发送给另一个不 相关的进程。
         管道服务端可以给管道服务端发送读句柄或者写句柄,这取决于客户端要用这个管道发送数据还是获取数据。要从管道读取数据,以管道的读句柄为参数调用 ReadFile函数。当另一个进程向管道写入数据是,ReadFile函数返回。如果管道的所有写句柄被关闭,或者读取数据时有错误发 生,ReadFile函数也会返回。
         要向管道写入数据,以管道的写句柄问参数,调用WriteFile函数。数据被完全写入管道,或者出错,WriteFile将会返回。如果管道的缓存已 满,且还有尚未写完的数据,直到另一个进程从管道读取数据前,WriteFile函数都不会返回。缓存的大小是在管道服务端调用CreatePipe函数 时指定的。
         匿名管道不支持异步读写。这意味着不能使用ReadFileEx和WriteFileEx函数读写匿名管道。另外,使用匿名管道时,ReadFile和WriteFile函数的lpOverlapped参数也会被忽略。
         匿名管道会一直存在,直到所有的读写句柄全部被关闭。进程可以调用CloseHandle函数关闭管道句柄。进程终止时,所有的管道句柄也会被自动关闭。
     
    双匿名管道实现通信

    #include <windows.h>
    #include <stdio.h>
    //双匿名管道实现写入读取
    int cmd_shell(SOCKET target)
    {	
    
    	STARTUPINFO g_stStartUp;
    	PROCESS_INFORMATION g_stProcInfo;
    	HANDLE reHandle1,wrHandle1;
    	HANDLE reHandle2,wrHandle2;
    	
    	char enter_key[2] = {0x0d,0x0a};
    	//填充SECURITY_ATTRIBUTES结构
    	SECURITY_ATTRIBUTES stSecurity;
    	
    	stSecurity.nLength = sizeof(SECURITY_ATTRIBUTES);
    	stSecurity.lpSecurityDescriptor = NULL;
    	stSecurity.bInheritHandle = TRUE;//继承性
    	//创建两个管道
    	CreatePipe(&reHandle1,&wrHandle1,&stSecurity,0);
    	CreatePipe(&reHandle2,&wrHandle2,&stSecurity,0);
    	//创建进程前填充STARTUPINFO结构
    	GetStartupInfo(&g_stStartUp);
    	g_stStartUp.hStdInput = reHandle1;
    	g_stStartUp.hStdOutput = wrHandle2;
    	g_stStartUp.hStdError = wrHandle2;
    	g_stStartUp.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
    	g_stStartUp.wShowWindow = SW_HIDE;
    	//创建进程CreateProcess启动这个控制台应用程序、
    	if(CreateProcess(NULL,"cmd.exe",NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,NULL,&g_stStartUp,&g_stProcInfo))
    	{
    		DWORD bytes_read,bytes_write,ret;
    		char buf[512] = {0};
    		while(1)
    		{
    			memset(buf,'\0',512);
    			PeekNamedPipe(reHandle2,buf,512,&bytes_read,NULL,NULL);
    			if(bytes_read != 0)
    			{
    				ret = ReadFile(reHandle2,buf,bytes_read,&bytes_read,NULL);
    				send(target,buf,strlen(buf),0);
    				if(ret<=0)
    				{
    					fprintf(stderr,"error on pipe %d",GetLastError());break;
    				}
    				
    			}
    			else
    			{
    				bytes_read = recv(target,buf,512,0);
    				printf("%s",buf);
    				if(bytes_read<=0)
    				{
    					fprintf(stderr,"error %d",GetLastError());
    				}
    				WriteFile(wrHandle1,buf,strlen(buf),&bytes_write,NULL);
    				WriteFile(wrHandle1,enter_key,2,&bytes_write,NULL);
    				if(strcmp(buf,"exit") == 0)
    				{
    					send(target,"连接关闭",8,0);
    					break;
    				}
    			
    			}
    			
    		}
    		Sleep(10);
    	}
    	printf("now Closing\n");
    	CloseHandle(g_stProcInfo.hProcess);
    	CloseHandle(g_stProcInfo.hThread);
    	printf("now closing Pipe\n");
    	return 0;
    }
    

    远程控制客户端加入匿名管道通信

    #include "stdafx.h"
    #include "客户端.h"
    #include "客户端Dlg.h"
    #include <winsock.h>
    #pragma comment(lib,"ws2_32")
    DWORD WINAPI ServerThread(LPVOID lparam);
    DWORD WINAPI GoThread(LPVOID lparam);
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    SOCKET server,client;
    SOCKADDR_IN serveraddr;
    char szGo[64];
    /////////////////////////////////////////////////////////////////////////////
    // CAboutDlg dialog used for App About
    
    class CAboutDlg : public CDialog
    {
    public:
    	CAboutDlg();
    
    // Dialog Data
    	//{{AFX_DATA(CAboutDlg)
    	enum { IDD = IDD_ABOUTBOX };
    	//}}AFX_DATA
    
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CAboutDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL
    
    // Implementation
    protected:
    	//{{AFX_MSG(CAboutDlg)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    	//{{AFX_DATA_INIT(CAboutDlg)
    	//}}AFX_DATA_INIT
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CAboutDlg)
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    	//{{AFX_MSG_MAP(CAboutDlg)
    		// No message handlers
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CMyDlg dialog
    
    CMyDlg::CMyDlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CMyDlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CMyDlg)
    	m_ipaddr = _T("");
    	m_port = 0;
    	//}}AFX_DATA_INIT
    	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
    void CMyDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CMyDlg)
    	DDX_Text(pDX, IDC_IPADDR, m_ipaddr);
    	DDX_Text(pDX, IDC_PORT, m_port);
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CMyDlg, CDialog)
    	//{{AFX_MSG_MAP(CMyDlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	ON_BN_CLICKED(IDC_CONNECT, OnConnect)
    	ON_BN_CLICKED(IDC_GO, OnGo)
    	ON_BN_CLICKED(IDC_CLEAR, OnClear)
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CMyDlg message handlers
    
    BOOL CMyDlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	//初始化库
    	
    	SetDlgItemText(IDC_IPADDR,"127.0.0.1");
    	SetDlgItemText(IDC_PORT,"1234");
    	UpdateData(true);
    	WSADATA wsadata;
    	WORD word = MAKEWORD(2,2);
    	WSAStartup(word,&wsadata);
    	
    	
    
    
    	
    	
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    void CMyDlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		dlgAbout.DoModal();
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }
    
    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.
    
    void CMyDlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    	}
    }
    
    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CMyDlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }
    
    void CMyDlg::OnConnect() 
    {
    	UpdateData(true);	
    	CreateThread(NULL,NULL,ServerThread,this,NULL,NULL);
    
    }
    DWORD WINAPI ServerThread(LPVOID lparam)
    {
    	CMyDlg *pDlg = (CMyDlg *)lparam;
    	
    
    	server = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    	
    	serveraddr.sin_family = AF_INET;
    	serveraddr.sin_port = htons(pDlg->m_port);
    	serveraddr.sin_addr.S_un.S_addr = inet_addr(pDlg->m_ipaddr);
    	client = connect(server,(SOCKADDR *)&serveraddr,sizeof(serveraddr));
    	if(client == SOCKET_ERROR)
    	{
    		MessageBox(NULL,"SORRY","连接出错",MB_OK);
    		return -1;
    	}
    	MessageBox(NULL,"CONGRATULATE!","连接成功",MB_OK);
    	pDlg->SetDlgItemText(IDC_INFO,"连接成功");
    	
    	char szRecv[1024];
    	CString str0,str1;
    	memset(szRecv,0,1024);
    	while(1)
    	{
    		
    		recv(server,szRecv,1024,0);
    		pDlg->GetDlgItemText(IDC_READ,str1);
    		str0 = szRecv;
    		str0 += "\r\n";
    		str0 += str1;
    		pDlg->SetDlgItemText(IDC_READ,str0);
    	}
    	return 0;
    }
    
    void CMyDlg::OnGo() 
    {
    	memset(szGo,0,64);
    	GetDlgItem(IDC_WRITE)->GetWindowTextA(szGo,64);
    	CreateThread(NULL,0,GoThread,this,NULL,NULL);
    
    }
    DWORD WINAPI GoThread(LPVOID lparam)
    {
    	CMyDlg *pDlg = (CMyDlg *)lparam;
    	
    	
    	char enter_key[2] = {0x0d,0x0a};
    	send(server,szGo,sizeof(szGo),0);
    	if(strcmp(szGo,"exit") == 0)
    	{
    		Sleep(100);
    		pDlg->SetDlgItemText(IDC_INFO,"未连接");
    		closesocket(server);
    		closesocket(client);
    		WSACleanup();
    		exit(0);
    	}
    	
    	return 0;
    }
    
    void CMyDlg::OnClear() 
    {
    	SetDlgItemText(IDC_READ,"");
    	
    }
    
    
    
    


     


     

  • 相关阅读:
    【开卷故意】JAVA正則表達式模版
    CSS控制显示超出部分,用省略号显示
    1星《微信软文营销实战技巧》:标题党,作者没有实战经验
    3星|《强势谈判》:有趣的绑匪谈判故事
    3星|《赢者的诅咒》:新晋诺奖得主92年作品,博弈论在拍卖、薪酬、股市、彩票、赛马、汇市等领域的应用,偏专业
    4星|《OKR实践指南》:老司机经验谈
    3星|《华为管理变革》:华为有史以来为了变革而开展的项目的概述。
    3星|《信号》:全球经济的坏消息
    2星|《麦肯锡图表工作法》:用图表做商业分析的入门演示
    2星|《麦肯锡与贝恩的团队管理智慧》:从投入、产出两个维度把下属分到4个象限
  • 原文地址:https://www.cnblogs.com/new0801/p/6177776.html
Copyright © 2020-2023  润新知