MFC- 网络编程

匆匆过客 提交于 2019-11-29 08:30:38

一、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 实现效果

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!