MFC多客户端与一个服务器通信 跑通Windows Demo

1. 简介
本教程旨在指导您如何使用Microsoft Foundation Classes (MFC) 在Windows平台上创建一个多客户端与一个服务器通信的简单Demo,我们将使用TCP/IP协议来实现客户端和服务器之间的数据传输。
2. 环境准备
Visual Studio 2019 或更高版本
Windows 10 或更高版本
3. 创建项目
1、打开Visual Studio,选择“创建新项目”。
2、在“创建新项目”对话框中,选择“MFC AppWizard (Visual C++)”。
3、在“应用程序类型”中选择“Win32 Application”。
4、在“Win32应用程序类型”中选择“Single Document”。
5、点击“下一步”,在“应用程序设置”中输入项目名称,如“MultiClientServerDemo”。
6、点击“完成”创建项目。
4. 服务器端实现

4.1 添加必要的头文件
在服务器端的头文件中,添加以下头文件:
#include <winsock2.h> #include <ws2tcpip.h> #include <iostream> #include <vector> #include "CServerSocket.h"
4.2 服务器类定义
定义一个CServerSocket类,用于管理服务器端的套接字和客户端连接。
class CServerSocket : public CSocket
{
public:
CServerSocket() {}
~CServerSocket() {}
BOOL StartServer(int port);
void AcceptClient();
void CloseClient(CSocket* pClientSocket);
void SendMessageToClient(CSocket* pClientSocket, const char* message);
void BroadcastMessage(const char* message);
};
4.3 服务器类实现
实现CServerSocket类的方法,如下所示:
BOOL CServerSocket::StartServer(int port)
{
WSADATA wsaData;
SOCKET listenSocket;
sockaddr_in server;
// 初始化Winsock
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 创建套接字
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listenSocket == INVALID_SOCKET)
{
std::cerr << "Failed to create socket: " << WSAGetLastError() << std::endl;
return FALSE;
}
// 设置服务器地址结构
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(port);
// 绑定套接字
if (bind(listenSocket, (SOCKADDR*)&server, sizeof(server)) == SOCKET_ERROR)
{
std::cerr << "Failed to bind socket: " << WSAGetLastError() << std::endl;
closesocket(listenSocket);
WSACleanup();
return FALSE;
}
// 监听连接
listen(listenSocket, 5);
return TRUE;
}
void CServerSocket::AcceptClient()
{
sockaddr_in client;
int clientSize = sizeof(client);
SOCKET clientSocket = accept(listenSocket, (SOCKADDR*)&client, &clientSize);
if (clientSocket == INVALID_SOCKET)
{
std::cerr << "Failed to accept client: " << WSAGetLastError() << std::endl;
return;
}
// 处理客户端连接
// ...
}
void CServerSocket::CloseClient(CSocket* pClientSocket)
{
closesocket(pClientSocket>GetSocket());
}
void CServerSocket::SendMessageToClient(CSocket* pClientSocket, const char* message)
{
int sent = send(pClientSocket>GetSocket(), message, strlen(message), 0);
if (sent == SOCKET_ERROR)
{
std::cerr << "Failed to send message: " << WSAGetLastError() << std::endl;
}
}
void CServerSocket::BroadcastMessage(const char* message)
{
for (auto it = clients.begin(); it != clients.end(); ++it)
{
SendMessageToClient(it>second, message);
}
}
4.4 主函数
在主函数中,创建CServerSocket对象,并启动服务器:
int main()
{
CServerSocket server;
if (server.StartServer(12345))
{
// 启动服务器循环
// ...
}
WSACleanup();
return 0;
}
5. 客户端实现
5.1 添加必要的头文件
在客户端的头文件中,添加以下头文件:
#include <winsock2.h> #include <ws2tcpip.h> #include <iostream> #include "CClientSocket.h"
5.2 客户端类定义
定义一个CClientSocket类,用于管理客户端的套接字。

class CClientSocket : public CSocket
{
public:
CClientSocket() {}
~CClientSocket() {}
BOOL ConnectToServer(const char* ip, int port);
void SendMessageToServer(const char* message);
void ReceiveMessageFromServer();
};
5.3 客户端类实现
实现CClientSocket类的方法,如下所示:
BOOL CClientSocket::ConnectToServer(const char* ip, int port)
{
WSADATA wsaData;
SOCKET clientSocket;
sockaddr_in server;
// 初始化Winsock
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 创建套接字
clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clientSocket == INVALID_SOCKET)
{
std::cerr << "Failed to create socket: " << WSAGetLastError() << std::endl;
return FALSE;
}
// 设置服务器地址结构
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr(ip);
server.sin_port = htons(port);
// 连接到服务器
if (connect(clientSocket, (SOCKADDR*)&server, sizeof(server)) == SOCKET_ERROR)
{
std::cerr << "Failed to connect to server: " << WSAGetLastError() << std::endl;
closesocket(clientSocket);
WSACleanup();
return FALSE;
}
return TRUE;
}
void CClientSocket::SendMessageToServer(const char* message)
{
int sent = send(GetSocket(), message, strlen(message), 0);
if (sent == SOCKET_ERROR)
{
std::cerr << "Failed to send message: " << WSAGetLastError() << std::endl;
}
}
void CClientSocket::ReceiveMessageFromServer()
{
char buffer[1024];
int received = recv(GetSocket(), buffer, sizeof(buffer), 0);
if (received > 0)
{
buffer[received] = '';
std::cout << "Received message: " << buffer << std::endl;
}
else if (received == 0)
{
std::cerr << "Server closed the connection" << std::endl;
}
else
{
std::cerr << "Failed to receive message: " << WSAGetLastError() << std::endl;
}
}
5.4 主函数
在主函数中,创建CClientSocket对象,并连接到服务器:
int main()
{
CClientSocket client;
if (client.ConnectToServer("127.0.0.1", 12345))
{
// 发送消息
client.SendMessageToServer("Hello, Server!");
// 接收消息
client.ReceiveMessageFromServer();
// 关闭连接
closesocket(client.GetSocket());
}
WSACleanup();
return 0;
}
6. 运行Demo
1、打开两个命令行窗口。
2、在第一个窗口中,编译并运行服务器端程序。
3、在第二个窗口中,编译并运行客户端程序。
客户端应该能够连接到服务器,并能够发送和接收消息。
7. 总结
本教程向您展示了如何使用MFC在Windows平台上创建一个多客户端与一个服务器通信的简单Demo,您可以根据需要扩展此Demo,添加更多的功能,例如广播消息、多线程处理等。