帮我写一个MFC网络编程的程序
时间: 2023-08-28 18:10:55 浏览: 183
基于MFC的网络编程
好的,这里提供一个简单的MFC网络编程的程序,实现了客户端和服务器端的通信。
客户端代码:
```
#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
int main(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(nullptr);
if (hModule != nullptr)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
// TODO: 请更改错误代码以符合您的需要
wprintf(L"严重错误: MFC 初始化失败\n");
nRetCode = 1;
}
else
{
// 创建对话框并运行
CClientDlg dlg;
theApp.m_pMainWnd = &dlg;
nRetCode = dlg.DoModal();
}
}
else
{
// TODO: 请更改错误代码以符合您的需要
wprintf(L"严重错误: GetModuleHandle 失败\n");
nRetCode = 1;
}
return nRetCode;
}
```
服务器端代码:
```
#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CWinApp theApp;
using namespace std;
int main(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HMODULE hModule = ::GetModuleHandle(nullptr);
if (hModule != nullptr)
{
// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(hModule, nullptr, ::GetCommandLine(), 0))
{
// TODO: 请更改错误代码以符合您的需要
wprintf(L"严重错误: MFC 初始化失败\n");
nRetCode = 1;
}
else
{
// 创建对话框并运行
CServerDlg dlg;
theApp.m_pMainWnd = &dlg;
nRetCode = dlg.DoModal();
}
}
else
{
// TODO: 请更改错误代码以符合您的需要
wprintf(L"严重错误: GetModuleHandle 失败\n");
nRetCode = 1;
}
return nRetCode;
}
```
客户端对话框代码:
```
#include "stdafx.h"
#include "Client.h"
#include "ClientDlg.h"
#include <winsock2.h>
#include <iostream>
#include <string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define BUFFER_SIZE 1024
CClientDlg::CClientDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_CLIENT_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_EditBox);
DDX_Control(pDX, IDC_SEND, m_SendButton);
DDX_Control(pDX, IDC_IPADDRESS1, m_ServerIP);
DDX_Control(pDX, IDC_PORT, m_Port);
}
BEGIN_MESSAGE_MAP(CClientDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_SEND, &CClientDlg::OnBnClickedSend)
ON_WM_CLOSE()
END_MESSAGE_MAP()
BOOL CClientDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
MessageBox(_T("Failed to load Winsock library!"), _T("Error"), MB_ICONERROR | MB_OK);
return FALSE;
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 将图标居中绘制
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
HCURSOR CClientDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CClientDlg::OnClose()
{
WSACleanup();
CDialogEx::OnClose();
}
void CClientDlg::OnBnClickedSend()
{
// 获取服务器IP和端口号
CString serverIPStr;
m_ServerIP.GetWindowText(serverIPStr);
char* serverIP = CStringA(serverIPStr).GetBuffer();
CString portStr;
m_Port.GetWindowText(portStr);
int port = _ttoi(portStr);
// 创建socket
SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET) {
MessageBox(_T("Failed to create socket!"), _T("Error"), MB_ICONERROR | MB_OK);
return;
}
// 设置服务器地址
SOCKADDR_IN serverAddr;
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = inet_addr(serverIP);
// 连接服务器
if (connect(sock, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
MessageBox(_T("Failed to connect to server!"), _T("Error"), MB_ICONERROR | MB_OK);
closesocket(sock);
return;
}
// 发送数据
CString msg;
m_EditBox.GetWindowText(msg);
char* buffer = CStringA(msg).GetBuffer();
int len = strlen(buffer);
send(sock, buffer, len, 0);
// 接收数据
char recvBuffer[BUFFER_SIZE] = {};
int recvLen = recv(sock, recvBuffer, BUFFER_SIZE, 0);
CString recvMsg = CString(recvBuffer, recvLen);
MessageBox(recvMsg, _T("Message Received"), MB_ICONINFORMATION | MB_OK);
// 关闭socket
closesocket(sock);
}
```
服务器端对话框代码:
```
#include "stdafx.h"
#include "Server.h"
#include "ServerDlg.h"
#include <winsock2.h>
#include <iostream>
#include <string>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
#define BUFFER_SIZE 1024
CServerDlg::CServerDlg(CWnd* pParent /*=nullptr*/)
: CDialogEx(IDD_SERVER_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CServerDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_EDIT1, m_EditBox);
DDX_Control(pDX, IDC_LISTEN, m_ListenButton);
DDX_Control(pDX, IDC_PORT, m_Port);
}
BEGIN_MESSAGE_MAP(CServerDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_LISTEN, &CServerDlg::OnBnClickedListen)
ON_WM_CLOSE()
END_MESSAGE_MAP()
BOOL CServerDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != nullptr)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
MessageBox(_T("Failed to load Winsock library!"), _T("Error"), MB_ICONERROR | MB_OK);
return FALSE;
}
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
void CServerDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // 用于绘制的设备上下文
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// 将图标居中绘制
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;
// 绘制图标
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
HCURSOR CServerDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CServerDlg::OnClose()
{
WSACleanup();
CDialogEx::OnClose();
}
void CServerDlg::OnBnClickedListen()
{
// 获取监听端口号
CString portStr;
m_Port.GetWindowText(portStr);
int port = _ttoi(portStr);
// 创建socket
SOCKET listenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSock == INVALID_SOCKET) {
MessageBox(_T("Failed to create socket!"), _T("Error"), MB_ICONERROR | MB_OK);
return;
}
// 设置本地地址
SOCKADDR_IN localAddr;
localAddr.sin_family = AF_INET;
localAddr.sin_port = htons(port);
localAddr.sin_addr.s_addr = htonl(INADDR_ANY);
// 绑定本地地址
if (bind(listenSock, (SOCKADDR*)&localAddr, sizeof(localAddr)) == SOCKET_ERROR) {
MessageBox(_T("Failed to bind socket!"), _T("Error"), MB_ICONERROR | MB_OK);
closesocket(listenSock);
return;
}
// 监听
if (listen(listenSock, SOMAXCONN) == SOCKET_ERROR) {
MessageBox(_T("Failed to listen socket!"), _T("Error"), MB_ICONERROR | MB_OK);
closesocket(listenSock);
return;
}
// 接受连接请求
SOCKADDR_IN clientAddr;
int clientAddrSize = sizeof(clientAddr);
SOCKET clientSock = accept(listenSock, (SOCKADDR*)&clientAddr, &clientAddrSize);
if (clientSock == INVALID_SOCKET) {
MessageBox(_T("Failed to accept connection!"), _T("Error"), MB_ICONERROR | MB_OK);
closesocket(listenSock);
return;
}
// 接收数据
char recvBuffer[BUFFER_SIZE] = {};
int recvLen = recv(clientSock, recvBuffer, BUFFER_SIZE, 0);
CString recvMsg = CString(recvBuffer, recvLen);
MessageBox(recvMsg, _T("Message Received"), MB_ICONINFORMATION | MB_OK);
// 发送数据
CString msg;
m_EditBox.GetWindowText(msg);
char* buffer = CStringA(msg).GetBuffer();
int len = strlen(buffer);
send(clientSock, buffer, len, 0);
// 关闭socket
closesocket(clientSock);
closesocket(listenSock);
}
```
注意事项:
1. 在使用Winsock库之前,需要先调用WSAStartup函数进行初始化。
2. 在使用socket函数创建套接字之前,需要先指定协议族、套接字类型和协议类型。
3. 在使用bind函数将套接字绑定到本地地址之前,需要先指定本地地址的IP地址、端口号和协议族。
4. 在使用listen函数进行监听之前,需要先指定backlog参数,表示等待连接队列的最大长度。
5. 在使用accept函数接受客户端连接请求之前,需要先指定客户端地址结构体的大小。
6. 在使用send和recv函数发送和接收数据时,需要注意缓冲区的大小。
阅读全文