MFC- 网络编程

Posted 506941763lcj

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MFC- 网络编程相关的知识,希望对你有一定的参考价值。

一、MFC网络编程

a)CAsyncSocket用于异步非阻塞类,用UDP通信;

b)CAsyncSocket的子类(派生类);Csocket同步阻塞类,用于TCP通信;

c)通信前,必须调用AfxSocketInit()进行初始化

二、CAsyncSocket类UDP通信

2.1 服务器端通信步骤:

a)在.h文件中创建CAsyncSocket类对象;

b)创建套接字CAsyncSocket::Create();

c)发送数据CAsyncSocket::SentTo();

d)关闭套接字CAsyncSocket::Close();

2.2 MFC界面

技术图片

2.3 代码实例:

a)01_UDPServerDlg.h中添加CAsyncSocket对象

技术图片
 1 // 01_UDPServerDlg.h : 头文件
 2 //
 3 
 4 #pragma once
 5 #include "afxcmn.h"
 6 #include "afxwin.h"
 7 
 8 
 9 // CMy01_UDPServerDlg 对话框
10 class CMy01_UDPServerDlg : public CDialogEx
11 
12 // 构造
13 public:
14     CMy01_UDPServerDlg(CWnd* pParent = NULL);    // 标准构造函数
15 
16 // 对话框数据
17     enum  IDD = IDD_MY01_UDPSERVER_DIALOG ;
18 
19     protected:
20     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
21 
22 
23 // 实现
24 protected:
25     HICON m_hIcon;
26 
27     // 生成的消息映射函数
28     virtual BOOL OnInitDialog();
29     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
30     afx_msg void OnPaint();
31     afx_msg HCURSOR OnQueryDragIcon();
32     DECLARE_MESSAGE_MAP()
33 private:
34     //自定义添加代码,MFC界面对应控件变量
35     UINT peerPort;
36     UINT localPort;
37     CIPAddressCtrl addrCtrl;
38     CString sendBuf;
39     int sendLen;
40     CButton startButton;
41     CButton stopButton;
42 
43     //套接字对象
44     CAsyncSocket socket;
45 public:
46     afx_msg void OnBnClickedButton1();
47     afx_msg void OnTimer(UINT_PTR nIDEvent);
48     afx_msg void OnBnClickedButton2();
49 ;
View Code

b)01_UDPServerDlg.cpp中初始化各变量,并实现通信套接字的创建,接受及关闭

技术图片
  1 // 01_UDPServerDlg.cpp : 实现文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "01_UDPServer.h"
  6 #include "01_UDPServerDlg.h"
  7 #include "afxdialogex.h"
  8 
  9 #ifdef _DEBUG
 10 #define new DEBUG_NEW
 11 #endif
 12 
 13 
 14 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
 15 
 16 class CAboutDlg : public CDialogEx
 17 
 18 public:
 19     CAboutDlg();
 20 
 21 // 对话框数据
 22     enum  IDD = IDD_ABOUTBOX ;
 23 
 24     protected:
 25     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
 26 
 27 // 实现
 28 protected:
 29     DECLARE_MESSAGE_MAP()
 30 ;
 31 
 32 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
 33 
 34 
 35 
 36 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 37 
 38     CDialogEx::DoDataExchange(pDX);
 39 
 40 
 41 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 42 END_MESSAGE_MAP()
 43 
 44 
 45 // CMy01_UDPServerDlg 对话框
 46 
 47 
 48 
 49 CMy01_UDPServerDlg::CMy01_UDPServerDlg(CWnd* pParent /*=NULL*/)
 50     : CDialogEx(CMy01_UDPServerDlg::IDD, pParent)
 51     , peerPort(0)
 52     , localPort(0)
 53     , sendBuf(_T(""))
 54     , sendLen(0)
 55 
 56     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 57 
 58 
 59 void CMy01_UDPServerDlg::DoDataExchange(CDataExchange* pDX)
 60 
 61     CDialogEx::DoDataExchange(pDX);
 62     DDX_Text(pDX, IDC_EDIT1, peerPort);
 63     DDX_Text(pDX, IDC_EDIT2, localPort);
 64     DDX_Control(pDX, IDC_IPADDRESS1, addrCtrl);
 65     DDX_Text(pDX, IDC_EDIT3, sendBuf);
 66     DDX_Text(pDX, IDC_EDIT4, sendLen);
 67     DDX_Control(pDX, IDC_BUTTON1, startButton);
 68     DDX_Control(pDX, IDC_BUTTON2, stopButton);
 69 
 70 
 71 BEGIN_MESSAGE_MAP(CMy01_UDPServerDlg, CDialogEx)
 72     ON_WM_SYSCOMMAND()
 73     ON_WM_PAINT()
 74     ON_WM_QUERYDRAGICON()
 75     ON_BN_CLICKED(IDC_BUTTON1, &CMy01_UDPServerDlg::OnBnClickedButton1)
 76     ON_WM_TIMER()
 77     ON_BN_CLICKED(IDC_BUTTON2, &CMy01_UDPServerDlg::OnBnClickedButton2)
 78 END_MESSAGE_MAP()
 79 
 80 
 81 // CMy01_UDPServerDlg 消息处理程序
 82 
 83 BOOL CMy01_UDPServerDlg::OnInitDialog()
 84 
 85     CDialogEx::OnInitDialog();
 86 
 87     // 将“关于...”菜单项添加到系统菜单中。
 88 
 89     // IDM_ABOUTBOX 必须在系统命令范围内。
 90     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 91     ASSERT(IDM_ABOUTBOX < 0xF000);
 92 
 93     CMenu* pSysMenu = GetSystemMenu(FALSE);
 94     if (pSysMenu != NULL)
 95     
 96         BOOL bNameValid;
 97         CString strAboutMenu;
 98         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
 99         ASSERT(bNameValid);
100         if (!strAboutMenu.IsEmpty())
101         
102             pSysMenu->AppendMenu(MF_SEPARATOR);
103             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
104         
105     
106 
107     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
108     //  执行此操作
109     SetIcon(m_hIcon, TRUE);            // 设置大图标
110     SetIcon(m_hIcon, FALSE);        // 设置小图标
111 
112     // TODO:  在此添加额外的初始化代码
113     peerPort = 8888;
114     localPort = 9999;
115     sendBuf = _T("准备发送数据");
116     sendLen = 0;
117     //把内容更新到对应的编辑区
118     UpdateData(FALSE);
119 
120     addrCtrl.SetAddress(127, 0, 0, 1);
121 
122     stopButton.EnableWindow(FALSE);
123 
124     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
125 
126 
127 void CMy01_UDPServerDlg::OnSysCommand(UINT nID, LPARAM lParam)
128 
129     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
130     
131         CAboutDlg dlgAbout;
132         dlgAbout.DoModal();
133     
134     else
135     
136         CDialogEx::OnSysCommand(nID, lParam);
137     
138 
139 
140 // 如果向对话框添加最小化按钮,则需要下面的代码
141 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
142 //  这将由框架自动完成。
143 
144 void CMy01_UDPServerDlg::OnPaint()
145 
146     if (IsIconic())
147     
148         CPaintDC dc(this); // 用于绘制的设备上下文
149 
150         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
151 
152         // 使图标在工作区矩形中居中
153         int cxIcon = GetSystemMetrics(SM_CXICON);
154         int cyIcon = GetSystemMetrics(SM_CYICON);
155         CRect rect;
156         GetClientRect(&rect);
157         int x = (rect.Width() - cxIcon + 1) / 2;
158         int y = (rect.Height() - cyIcon + 1) / 2;
159 
160         // 绘制图标
161         dc.DrawIcon(x, y, m_hIcon);
162     
163     else
164     
165         CDialogEx::OnPaint();
166     
167 
168 
169 //当用户拖动最小化窗口时系统调用此函数取得光标
170 //显示。
171 HCURSOR CMy01_UDPServerDlg::OnQueryDragIcon()
172 
173     return static_cast<HCURSOR>(m_hIcon);
174 
175 
176 //发送按钮
177 void CMy01_UDPServerDlg::OnBnClickedButton1()
178 
179     // TODO:  在此添加控件通知处理程序代码
180 
181     //把编辑区的内容更新到对应的变量中
182     UpdateData(TRUE);
183 
184     //创建UDP套接字
185     if (socket.Create(localPort, SOCK_DGRAM) )
186     
187         //启动定时器 处理 WM_TIMER消息
188         SetTimer(1, 500, NULL);
189 
190         //开始按钮变灰
191         startButton.EnableWindow(FALSE);
192         //停止按钮恢复
193         stopButton.EnableWindow(TRUE);
194     
195     else //套接字创建失败
196     
197         MessageBox(_T("创建套接字失败"));
198     
199 
200 
201 
202 //定时器回调函数
203 void CMy01_UDPServerDlg::OnTimer(UINT_PTR nIDEvent)
204 
205     // TODO:  在此添加消息处理程序代码和/或调用默认值
206 
207     //组包,要发送的数据包
208     char buf[32] =  0 ;
209     static int i = 0;
210     i++;
211     sprintf_s(buf, sizeof(buf), "%010d", i);
212 
213     //获取对方的IP和端口
214     UpdateData(TRUE); //获取编辑区的值
215     BYTE a, b, c, d;
216     addrCtrl.GetAddress(a, b, c, d);
217     CString ip;
218     ip.Format(_T("%d.%d.%d.%d"), a, b, c, d);
219 
220     //发送数据包
221     int len = socket.SendTo(buf, strlen(buf), peerPort, ip);
222     if (len > 0)
223     
224         sendBuf = CString(buf); //char * -> CString
225         sendLen += len;
226 
227         //把对应的值更新到编辑区
228         UpdateData(FALSE);
229     
230 
231     CDialogEx::OnTimer(nIDEvent);
232 
233 
234 
235 void CMy01_UDPServerDlg::OnBnClickedButton2()
236 
237     // TODO:  在此添加控件通知处理程序代码
238     sendBuf = _T("数据已经停止发送");
239     UpdateData(FALSE);
240 
241     socket.Close(); //关闭套接字
242     KillTimer(1); //关闭定时器
243 
244     startButton.EnableWindow(TRUE);
245     stopButton.EnableWindow(FALSE);
246 
View Code

2.3  客户端通信步骤:

a)在.h中创建CAsyncSocket类对象;

b)创建套接字CAsyncSocket::Create();

c)接受数据CAsyncSocket::ReceiveFrom();

d)关闭套接字CAsyncSocket::Close();

2.4 客户端MFC界面

技术图片

2.3  01_UDPClientDlg.h中添加类

技术图片
 1 // 01_UDPClientDlg.h : 头文件
 2 //
 3 
 4 #pragma once
 5 #include "afxwin.h"
 6 
 7 
 8 // CMy01_UDPClientDlg 对话框
 9 class CMy01_UDPClientDlg : public CDialogEx
10 
11 // 构造
12 public:
13     CMy01_UDPClientDlg(CWnd* pParent = NULL);    // 标准构造函数
14 
15 // 对话框数据
16     enum  IDD = IDD_MY01_UDPCLIENT_DIALOG ;
17 
18     protected:
19     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
20 
21 
22 // 实现
23 protected:
24     HICON m_hIcon;
25 
26     // 生成的消息映射函数
27     virtual BOOL OnInitDialog();
28     afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
29     afx_msg void OnPaint();
30     afx_msg HCURSOR OnQueryDragIcon();
31     DECLARE_MESSAGE_MAP()
32 private:
33     //自定义代码区
34     UINT peerPort;
35     UINT localPort;
36     CString peerIP;
37     CString recvBuf;
38     int recvLen;
39     CButton startButton;
40     CButton stopButton;
41     CAsyncSocket socket;
42 public:
43     afx_msg void OnBnClickedButton1();
44     afx_msg void OnTimer(UINT_PTR nIDEvent);
45     afx_msg void OnBnClickedButton2();
46 ;
View Code

2.4  01_UDPClientDlg.cpp中初始化,并创建、接受、关闭套接字

技术图片
  1 // 01_UDPClientDlg.cpp : 实现文件
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "01_UDPClient.h"
  6 #include "01_UDPClientDlg.h"
  7 #include "afxdialogex.h"
  8 
  9 #ifdef _DEBUG
 10 #define new DEBUG_NEW
 11 #endif
 12 
 13 
 14 // 用于应用程序“关于”菜单项的 CAboutDlg 对话框
 15 
 16 class CAboutDlg : public CDialogEx
 17 
 18 public:
 19     CAboutDlg();
 20 
 21 // 对话框数据
 22     enum  IDD = IDD_ABOUTBOX ;
 23 
 24     protected:
 25     virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持
 26 
 27 // 实现
 28 protected:
 29     DECLARE_MESSAGE_MAP()
 30 ;
 31 
 32 CAboutDlg::CAboutDlg() : CDialogEx(CAboutDlg::IDD)
 33 
 34 
 35 
 36 void CAboutDlg::DoDataExchange(CDataExchange* pDX)
 37 
 38     CDialogEx::DoDataExchange(pDX);
 39 
 40 
 41 BEGIN_MESSAGE_MAP(CAboutDlg, CDialogEx)
 42 END_MESSAGE_MAP()
 43 
 44 
 45 // CMy01_UDPClientDlg 对话框
 46 
 47 
 48 
 49 CMy01_UDPClientDlg::CMy01_UDPClientDlg(CWnd* pParent /*=NULL*/)
 50     : CDialogEx(CMy01_UDPClientDlg::IDD, pParent)
 51     , peerPort(0)
 52     , localPort(0)
 53     , peerIP(_T(""))
 54     , recvBuf(_T(""))
 55     , recvLen(0)
 56 
 57     m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
 58 
 59 
 60 void CMy01_UDPClientDlg::DoDataExchange(CDataExchange* pDX)
 61 
 62     CDialogEx::DoDataExchange(pDX);
 63     DDX_Text(pDX, IDC_EDIT1, peerPort);
 64     DDX_Text(pDX, IDC_EDIT2, localPort);
 65     DDX_Text(pDX, IDC_EDIT3, peerIP);
 66     DDX_Text(pDX, IDC_EDIT4, recvBuf);
 67     DDX_Text(pDX, IDC_EDIT5, recvLen);
 68     DDX_Control(pDX, IDC_BUTTON1, startButton);
 69     DDX_Control(pDX, IDC_BUTTON2, stopButton);
 70 
 71 
 72 BEGIN_MESSAGE_MAP(CMy01_UDPClientDlg, CDialogEx)
 73     ON_WM_SYSCOMMAND()
 74     ON_WM_PAINT()
 75     ON_WM_QUERYDRAGICON()
 76     ON_BN_CLICKED(IDC_BUTTON1, &CMy01_UDPClientDlg::OnBnClickedButton1)
 77     ON_WM_TIMER()
 78     ON_BN_CLICKED(IDC_BUTTON2, &CMy01_UDPClientDlg::OnBnClickedButton2)
 79 END_MESSAGE_MAP()
 80 
 81 
 82 // CMy01_UDPClientDlg 消息处理程序
 83 
 84 BOOL CMy01_UDPClientDlg::OnInitDialog()
 85 
 86     CDialogEx::OnInitDialog();
 87 
 88     // 将“关于...”菜单项添加到系统菜单中。
 89 
 90     // IDM_ABOUTBOX 必须在系统命令范围内。
 91     ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
 92     ASSERT(IDM_ABOUTBOX < 0xF000);
 93 
 94     CMenu* pSysMenu = GetSystemMenu(FALSE);
 95     if (pSysMenu != NULL)
 96     
 97         BOOL bNameValid;
 98         CString strAboutMenu;
 99         bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
100         ASSERT(bNameValid);
101         if (!strAboutMenu.IsEmpty())
102         
103             pSysMenu->AppendMenu(MF_SEPARATOR);
104             pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
105         
106     
107 
108     // 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动
109     //  执行此操作
110     SetIcon(m_hIcon, TRUE);            // 设置大图标
111     SetIcon(m_hIcon, FALSE);        // 设置小图标
112 
113     // TODO:  在此添加额外的初始化代码
114     localPort = 8888;
115     peerPort = 9999;
116     peerIP = _T("127.0.0.1");
117 
118     recvBuf = _T("准备接收数据……");
119     recvLen = 0;
120 
121     //把值更新到对应的编辑区
122     UpdateData(FALSE);
123 
124     stopButton.EnableWindow(FALSE);
125 
126     return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
127 
128 
129 void CMy01_UDPClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
130 
131     if ((nID & 0xFFF0) == IDM_ABOUTBOX)
132     
133         CAboutDlg dlgAbout;
134         dlgAbout.DoModal();
135     
136     else
137     
138         CDialogEx::OnSysCommand(nID, lParam);
139     
140 
141 
142 // 如果向对话框添加最小化按钮,则需要下面的代码
143 //  来绘制该图标。  对于使用文档/视图模型的 MFC 应用程序,
144 //  这将由框架自动完成。
145 
146 void CMy01_UDPClientDlg::OnPaint()
147 
148     if (IsIconic())
149     
150         CPaintDC dc(this); // 用于绘制的设备上下文
151 
152         SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
153 
154         // 使图标在工作区矩形中居中
155         int cxIcon = GetSystemMetrics(SM_CXICON);
156         int cyIcon = GetSystemMetrics(SM_CYICON);
157         CRect rect;
158         GetClientRect(&rect);
159         int x = (rect.Width() - cxIcon + 1) / 2;
160         int y = (rect.Height() - cyIcon + 1) / 2;
161 
162         // 绘制图标
163         dc.DrawIcon(x, y, m_hIcon);
164     
165     else
166     
167         CDialogEx::OnPaint();
168     
169 
170 
171 //当用户拖动最小化窗口时系统调用此函数取得光标
172 //显示。
173 HCURSOR CMy01_UDPClientDlg::OnQueryDragIcon()
174 
175     return static_cast<HCURSOR>(m_hIcon);
176 
177 
178 void CMy01_UDPClientDlg::OnBnClickedButton1()
179 
180     // TODO:  在此添加控件通知处理程序代码
181 
182     //把编辑区的内容更新到对应的变量中
183     UpdateData(TRUE);
184 
185     //创建UDP套接字
186     if (socket.Create(localPort, SOCK_DGRAM))
187     
188         //启动定时器 处理 WM_TIMER消息
189         SetTimer(1, 500, NULL);
190 
191         //开始按钮变灰
192         startButton.EnableWindow(FALSE);
193         //停止按钮恢复
194         stopButton.EnableWindow(TRUE);
195     
196     else //套接字创建失败
197     
198         MessageBox(_T("创建套接字失败"));
199     
200 
201 
202 //定时器回调函数
203 void CMy01_UDPClientDlg::OnTimer(UINT_PTR nIDEvent)
204 
205     // TODO:  在此添加消息处理程序代码和/或调用默认值
206 
207     UpdateData(TRUE);
208 
209     char buf[32] =  0 ;
210     int len = socket.ReceiveFrom(buf, sizeof(buf), peerIP, peerPort);
211     if (len > 0)
212     
213         recvBuf = CString(buf); // char * -> CString
214         recvLen += len;
215     
216     else
217     
218         recvBuf = _T("停止接收数据");
219         socket.Close();
220         KillTimer(1);
221         stopButton.EnableWindow(FALSE);
222         startButton.EnableWindow(TRUE);
223 
224     
225 
226     UpdateData(FALSE);
227 
228 
229     CDialogEx::OnTimer(nIDEvent);
230 
231 
232 
233 void CMy01_UDPClientDlg::OnBnClickedButton2()
234 
235     // TODO:  在此添加控件通知处理程序代码
236 
237     recvBuf = _T("数据已经停止接收");
238     UpdateData(FALSE);
239 
240     KillTimer(1); //关闭定时器
241     socket.Close(); //关闭套接字
242     
243 
244     startButton.EnableWindow(TRUE);
245     stopButton.EnableWindow(FALSE);
246 
View Code

2.5 实现效果

技术图片

 

以上是关于MFC- 网络编程的主要内容,如果未能解决你的问题,请参考以下文章

MFC- 网络编程

MFC编程 -- 添加菜单

MFC控件编程之鼠标消息

Visual C++/C# 中的 WinForms 编程与 Visual C++(MFC) 中的 Windows 编程有何不同

C++ socket编程 和 MFC socket编程 有啥区别??

MFC编程 -- 列表删除单行及多行操作