您的位置:首页 > 编程语言 > C语言/C++

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

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

匿名管道
匿名管道是一种未命名的、单向管道。通常用来在父进程和子进程之间传输数据。匿名管道总是本地的,不能在网络之间传递数据。
匿名管道操作
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,"");

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐