MFC多客户端同时与一个服务器通信,Windows Demo成功实现,这样的跨平台通信机制有何独特优势?

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

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. 服务器端实现

MFC多客户端同时与一个服务器通信,Windows Demo成功实现,这样的跨平台通信机制有何独特优势?

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类,用于管理客户端的套接字。

MFC多客户端同时与一个服务器通信,Windows Demo成功实现,这样的跨平台通信机制有何独特优势?

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,添加更多的功能,例如广播消息、多线程处理等。