MFC Winsock 类:MFC 中的网络编程

目录

概述

一.MFC Winsock 类简介

1.MFC Winsock 类的主要功能

2.MFC Winsock 类的主要优点

3.MFC Winsock 类的主要缺点

4.MFC Winsock 类的主要类

5.MFC Winsock 类示例

二.CAsyncSocket 类

1.主要功能

异步通信

事件驱动

数据传输

套接字选项

2.常用函数

创建套接字对象

连接到远程服务器

发送和接收数据

关闭套接字连接

处理网络事件的函数

三.CSocket 类

1.CSocket类的特点

2.主要功能

3.常用函数

四.MFC Winsock 编程模型

1.基于事件的编程模型

2.基于同步的编程模型

总结


概述

        MFC(Microsoft Foundation Class)是 Microsoft 公司提供的一套 C++ 类库,用于在 Windows 平台上开发桌面应用程序。MFC 提供了丰富的类和函数,简化了 Windows 应用程序的开发。除了用于开发传统 GUI 应用程序的类之外,MFC 还提供了用于网络编程的类,称为 MFC Winsock 类。

一.MFC Winsock 类简介

        MFC Winsock 类是 MFC 框架中用于网络编程的一套类,它封装了 Windows 操作系统中的 Winsock API(Windows Sockets API),为程序员提供了一套面向对象的接口来实现网络通信和数据传输。MFC Winsock 类简化了网络编程的过程,使程序员能够更容易地开发网络应用程序。

1.MFC Winsock 类的主要功能

  • 建立和管理网络连接
  • 发送和接收网络数据
  • 处理网络事件

2.MFC Winsock 类的主要优点

  • 面向对象,易于使用
  • 封装了 Winsock API 的复杂性
  • 提供了丰富的功能和工具

3.MFC Winsock 类的主要缺点

  • 执行效率较低
  • 增加了代码量

4.MFC Winsock 类的主要类

  • CSocket 类:用于建立和管理网络连接。
  • CAsyncSocket 类:用于异步网络通信。
  • CArchive 类:用于序列化和反序列化网络数据。

5.MFC Winsock 类示例

以下代码演示了如何使用 MFC Winsock 类建立一个 TCP 连接并发送数据:

CSocket socket;

// 建立连接
socket.Create();
socket.Connect(_T("127.0.0.1"), 80);

// 发送数据
CString strData = _T("Hello, World!");
socket.Send(strData.GetBuffer(), strData.GetLength());

// 关闭连接
socket.Close();

二.CAsyncSocket 类

        CAsyncSocket 类是 MFC Winsock 类库中的一个重要类,它提供了一个异步套接字对象,用于实现异步网络通信。异步套接字允许应用程序在发送或接收数据时不阻塞,从而提高了应用程序的响应能力。

1.主要功能

        CAsyncSocket类是MFC框架中用于异步网络编程的核心类,它封装了Windows Sockets API中的异步网络编程功能,为程序员提供了一套面向对象的接口来实现异步网络通信和数据传输。CAsyncSocket类具有以下主要功能:

异步通信

        CAsyncSocket类支持异步通信,这意味着应用程序在发送或接收数据时不阻塞,可以继续执行其他任务。这使得应用程序能够提高响应速度和处理效率,尤其是在需要同时处理多个网络连接的情况下。

CAsyncSocket类提供了以下异步通信功能:

  • 异步连接:应用程序可以使用CAsyncSocket类的Connect函数异步地建立网络连接。在连接建立完成后,CAsyncSocket类会触发一个连接事件通知应用程序。
  • 异步发送:应用程序可以使用CAsyncSocket类的Send函数异步地发送数据。在数据发送完成后,CAsyncSocket类会触发一个发送事件通知应用程序。
  • 异步接收:应用程序可以使用CAsyncSocket类的Receive函数异步地接收数据。在数据接收完成后,CAsyncSocket类会触发一个接收事件通知应用程序。
事件驱动

        CAsyncSocket类采用事件驱动机制来通知应用程序网络事件的发生。应用程序可以注册事件处理函数来响应CAsyncSocket类触发的各种事件,例如连接建立、数据接收、连接关闭等。

CAsyncSocket类支持以下事件:

  • 连接事件:连接建立时触发,通知应用程序连接已建立。
  • 发送事件:数据发送完成后触发,通知应用程序数据已发送。
  • 接收事件:数据接收完成后触发,通知应用程序数据已接收。
  • 错误事件:发生错误时触发,通知应用程序错误信息。
  • 关闭事件:连接关闭时触发,通知应用程序连接已关闭。
数据传输

        CAsyncSocket类提供了发送和接收数据的函数,应用程序可以发送或接收文本或二进制数据。

CAsyncSocket类支持以下数据传输功能:

  • 发送文本数据:应用程序可以使用CAsyncSocket类的SendString函数发送文本数据。
  • 发送二进制数据:应用程序可以使用CAsyncSocket类的Send函数发送二进制数据。
  • 接收文本数据:应用程序可以使用CAsyncSocket类的ReceiveString函数接收文本数据。
  • 接收二进制数据:应用程序可以使用CAsyncSocket类的Receive函数接收二进制数据。
套接字选项

        CAsyncSocket类提供了设置或获取套接字选项的函数,如超时时间、缓冲区大小等。套接字选项可以控制网络连接的行为和性能。

CAsyncSocket类支持以下套接字选项:

  • 超时时间:设置或获取连接超时时间和接收超时时间。
  • 缓冲区大小:设置或获取发送缓冲区大小和接收缓冲区大小。
  • 重传策略:设置或获取数据重传策略。

2.常用函数

        CAsyncSocket类是MFC框架中用于异步网络编程的核心类,它提供了丰富的函数来实现异步网络通信和数据传输。以下是一些CAsyncSocket类的常用函数:

创建套接字对象
  • Create():创建一个异步套接字对象。
CAsyncSocket socket;

// 创建套接字对象
socket.Create();
连接到远程服务器
  • Connect():连接到一个远程服务器。
// 连接到远程服务器
socket.Connect(_T("127.0.0.1"), 80);
发送和接收数据
  • Send():发送数据。
  • Receive():接收数据。
// 发送文本数据
CString strData = _T("Hello, World!");
socket.Send(strData.GetBuffer(), strData.GetLength());

// 接收文本数据
CString strRecv;
int nRecv = socket.Receive(strRecv.GetBuffer(), strRecv.GetBufferSize());
strRecv.ReleaseBuffer(nRecv);
关闭套接字连接
  • Close():关闭套接字连接。
// 关闭套接字连接
socket.Close();
处理网络事件的函数

CAsyncSocket类支持以下网络事件:

  • 连接事件:连接建立时触发,通知应用程序连接已建立。
  • 发送事件:数据发送完成后触发,通知应用程序数据已发送。
  • 接收事件:数据接收完成后触发,通知应用程序数据已接收。
  • 错误事件:发生错误时触发,通知应用程序错误信息。
  • 关闭事件:连接关闭时触发,通知应用程序连接已关闭。

        应用程序可以注册事件处理函数来响应CAsyncSocket类触发的各种事件。以下是一些常用的事件处理函数:

  • OnConnect():处理连接事件。
  • OnSend():处理发送事件。
  • OnReceive():处理接收事件。
  • OnError():处理错误事件。
  • OnClose():处理关闭事件。

例如,以下代码演示了如何注册事件处理函数:

socket.SetEventMask(
    FM_CONNECT | FM_SEND | FM_RECEIVE | FM_CLOSE | FM_ERROR
);

socket.AttachWindow(this);

三.CSocket 类

        CSocket类是MFC Winsock类库中的重要成员,它提供了一个同步套接字对象,用于实现同步网络通信。与异步套接字(CAsyncSocket)不同,CSocket在进行数据发送或接收时会阻塞主线程,直到操作完成或超时。

1.CSocket类的特点

  • 同步操作:CSocket的Send和Receive函数是阻塞式的,会在数据发送或接收完成或超时之前一直占用主线程。
  • 面向对象封装:CSocket封装了底层的Winsock API,为开发人员提供了更加直观易用的面向对象接口。
  • 便捷的数据管理:CSocket可以与CSocketFile和CArchive类协同工作,简化数据的发送和接收操作。

2.主要功能

        CSocket类是MFC框架中提供的一个用于网络编程的类,它封装了Windows Socket API,为开发人员提供了一个面向对象的编程接口。CSocket类的主要功能包括:

1. 同步通信

        CSocket类提供了同步的发送和接收数据函数,即SendReceive函数。在调用Send函数时,应用程序会阻塞等待数据发送完成,直到所有数据都被发送或发生错误为止。在调用Receive函数时,应用程序也会阻塞等待数据接收完成,直到接收指定数量的数据或发生错误为止。

        同步通信模式适用于需要保证数据传输可靠性的场景,例如文件传输、关键数据的传输等。

2. 数据传输

        CSocket类提供了发送和接收文本或二进制数据的函数,即SendTextReceiveTextSendBufferReceiveBuffer函数。SendTextReceiveText函数用于发送和接收文本数据,SendBufferReceiveBuffer函数用于发送和接收二进制数据。

        CSocket类支持多种数据格式的转换,包括文本格式(ANSI、Unicode)、二进制格式等。

3. 套接字选项

        CSocket类提供了设置或获取套接字选项的函数,即SetSocketOptionGetSocketOption函数。套接字选项用于控制套接字的行为,例如设置超时时间、缓冲区大小、重传策略等。

        设置合理的套接字选项可以提高网络通信的效率和可靠性。

4. 异常处理

        CSocket类提供了异常处理机制,当发生网络错误时会抛出异常,例如CNetworkExceptionCTimeoutException等。程序员可以捕获这些异常并进行相应的处理。

        异常处理机制可以简化网络编程的代码,提高程序的鲁棒性。

3.常用函数

        CSocket类提供了丰富的函数来满足各种网络编程需求,以下是一些常用的函数及其说明:

1. Create()

功能:创建一个同步套接字对象。

语法:

BOOL Create(AF_INET af, int type, int protocol);

参数说明:

  • af:地址家族,指定套接字使用的地址类型,例如AF_INET表示IPv4地址,AF_INET6表示IPv6地址。
  • type:套接字类型,例如SOCK_STREAM表示面向连接的套接字,SOCK_DGRAM表示无连接的套接字。
  • protocol:协议类型,指定套接字使用的协议,例如IPPROTO_TCP表示TCP协议,IPPROTO_UDP表示UDP协议。

返回值:

  • 成功创建套接字返回TRUE,失败返回FALSE。

示例代码:

CSocket socket;

// 创建一个IPv4、面向连接、使用TCP协议的套接字
BOOL bRet = socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (!bRet)
{
    AfxMessageBox(_T("Create socket failed!"));
    return;
}

2. Connect()

功能:连接到一个远程服务器。

语法:

BOOL Connect(LPCTSTR lpszAddress, UINT nPort);

参数说明:

  • lpszAddress:远程服务器的地址,可以是域名或IP地址。
  • nPort:远程服务器的端口号。

返回值:

  • 成功连接返回TRUE,失败返回FALSE。

示例代码:

CSocket socket;

// 创建一个套接字
socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 连接到服务器
BOOL bRet = socket.Connect(_T("127.0.0.1"), 80);
if (!bRet)
{
    AfxMessageBox(_T("Connect to server failed!"));
    return;
}

3. Send() 和 Receive()

功能:发送和接收数据。

语法:

int Send(LPVOID lpBuffer, int nBufferLen);
int Receive(LPVOID lpBuffer, int nBufferLen);

参数说明:

  • lpBuffer:指向要发送或接收数据的缓冲区的指针。
  • nBufferLen:缓冲区的大小。

返回值:

  • 发送或接收的数据字节数,如果发生错误则返回-1。

示例代码:

CSocket socket;

// 创建一个套接字
socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 连接到服务器
socket.Connect(_T("127.0.0.1"), 80);

// 发送数据
CString data = _T("Hello, World!");
int nSendBytes = socket.Send(data.GetBuffer(), data.GetLength());
if (nSendBytes == -1)
{
    AfxMessageBox(_T("Send data failed!"));
    return;
}

// 接收数据
char buffer[1024];
int nRecvBytes = socket.Receive(buffer, sizeof(buffer));
if (nRecvBytes == -1)
{
    AfxMessageBox(_T("Receive data failed!"));
    return;
}

// 处理接收到的数据
CString receivedData(buffer, nRecvBytes);
AfxMessageBox(receivedData);

4. Close()

功能:关闭套接字连接。

语法:

void Close();

 示例代码:

CSocket socket;

// 创建一个套接字
socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 连接到服务器
socket.Connect(_T("127.0.0.1"), 80);

// 发送数据
CString data = _T("Hello, World!");
int nSendBytes = socket.Send(data.GetBuffer(), data.GetLength());
if (nSendBytes == -1)
{
    AfxMessageBox(_T("Send data failed!"));
    return;
}

// 接收数据
char buffer[1024];
int nRecvBytes = socket.Receive(buffer, sizeof(buffer));
if (nRecvBytes == -1)
{
    AfxMessageBox(_T("Receive data failed!"));
    

四.MFC Winsock 编程模型

        MFC Winsock 类库提供了两种主要的编程模型:基于事件的编程模型和基于同步的编程模型。

1.基于事件的编程模型

        CAsyncSocket类除了支持同步通信外,还支持基于事件的异步通信。在异步通信模式下,应用程序在发送或接收数据时不会阻塞,而是继续执行其他操作。当网络事件发生时,MFC框架会调用应用程序指定的事件处理函数,应用程序可以在其中处理事件。

基于事件的编程模型具有以下优点:

  • 提高了应用程序的响应能力。应用程序在发送或接收数据时不会阻塞,可以继续执行其他操作,从而提高了应用程序的响应速度。
  • 降低了对CPU资源的占用。由于应用程序在等待网络事件时不会占用CPU资源,因此可以提高CPU资源的利用率。
  • 简化了程序的编写。基于事件的编程模型使用事件处理函数来处理网络事件,可以简化程序的编写。

以下是一些使用CAsyncSocket类进行异步网络编程的示例代码:

class CMySocket : public CSocket
{
public:
    CMySocket()
    {
        m_pWnd = NULL;
    }

    ~CMySocket()
    {
        m_pWnd = NULL;
    }

    DECLARE_DYNAMIC(CMySocket)

public:
    virtual void OnReceive(int nErrorCode, int nBytesTransfered, LPVOID lpBuffer)
    {
        if (nErrorCode == 0)
        {
            CString strData((char*)lpBuffer, nBytesTransfered);
            m_pWnd->PostMessage(WM_SOCKET_DATA, nBytesTransfered, (LPARAM)strData.GetBuffer());
        }
        else
        {
            AfxMessageBox(_T("Receive data failed!"));
        }
    }

    virtual void OnConnect(int nErrorCode)
    {
        if (nErrorCode == 0)
        {
            AfxMessageBox(_T("Connect to server successfully!"));
        }
        else
        {
            AfxMessageBox(_T("Connect to server failed!"));
        }
    }

private:
    CWnd* m_pWnd;
};

class CMyDlg : public CDialog
{
public:
    CMyDlg(CWnd* pParent = NULL) : CDialog(CMyDlg::IDD, pParent)
    {
    }

    enum { IDD = IDD_MYDLG };

protected:
    virtual void OnInitDialog()
    {
        CDialog::OnInitDialog();

        m_socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        m_socket.SetEventHandler(&m_socketEventHandler);
    }

    virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam)
    {
        if (wParam == ID_CONNECT)
        {
            BOOL bRet = m_socket.Connect(_T("127.0.0.1"), 80);
            if (!bRet)
            {
                AfxMessageBox(_T("Connect to server failed!"));
                return FALSE;
            }
        }
        else if (wParam == ID_SEND)
        {
            CString data = _T("Hello, World!");
            int nSendBytes = m_socket.Send(data.GetBuffer(), data.GetLength());
            if (nSendBytes == -1)
            {
                AfxMessageBox(_T("Send data failed!"));
                return FALSE;
            }
        }

        return TRUE;
    }

private:
    CMySocket m_socket;
    CMySocketEventHandler m_socketEventHandler;
};

class CMySocketEventHandler : public CAsyncSocketEventHandler
{
public:
    CMySocketEventHandler()
    {
        m_pDlg = NULL;
    }

    ~CMySocketEventHandler()
    {
        m_pDlg = NULL;
    }

    void SetDlg(CMyDlg* pDlg)
    {
        m_pDlg = pDlg;
    }

public:
    virtual void OnReceive(int nErrorCode, int nBytesTransfered, LPVOID lpBuffer)
    {
        if (m_pDlg)
        {
            m_pDlg->PostMessage(WM_SOCKET_DATA, nBytesTransfered, (LPARAM)lpBuffer);
        }
    }

    virtual void OnConnect(int nErrorCode)
    {
        if (m_pDlg)
        {
            if (nErrorCode == 0)
            {
                m_pDlg->PostMessage(WM_SOCKET_CONNECT, 

2.基于同步的编程模型

        基于同步的编程模型使用CSocket类实现同步网络通信。应用程序创建一个同步套接字对象,并调用同步的发送和接收数据函数。这些函数在操作完成或超时之前是阻塞的。这意味着应用程序在调用这些函数时会一直等待,直到数据发送或接收完成,或者发生错误为止。

基于同步的编程模型具有以下优点:

  • 简化了网络编程的过程。同步的发送和接收数据函数使用起来非常简单,应用程序只需调用这些函数并等待结果即可。
  • 保证了数据完整性和顺序。由于同步的发送和接收数据函数是阻塞的,因此可以保证数据完整性和顺序。

但是,基于同步的编程模型也存在以下缺点:

  • 降低了应用程序的响应能力。由于应用程序在发送或接收数据时会阻塞,因此会降低应用程序的响应能力。
  • 占用CPU资源。由于应用程序在等待网络事件时会占用CPU资源,因此会降低CPU资源的利用率。

以下是一些使用CSocket类进行同步网络编程的示例代码:

CSocket socket;

// 创建一个套接字
socket.Create(AF_INET, SOCK_STREAM, IPPROTO_TCP);

// 连接到服务器
socket.Connect(_T("127.0.0.1"), 80);

// 发送数据
CString data = _T("Hello, World!");
int nSendBytes = socket.Send(data.GetBuffer(), data.GetLength());
if (nSendBytes == -1)
{
    AfxMessageBox(_T("Send data failed!"));
    return;
}

// 接收数据
char buffer[1024];
int nRecvBytes = socket.Receive(buffer, sizeof(buffer));
if (nRecvBytes == -1)
{
    AfxMessageBox(_T("Receive data failed!"));
    return;
}

// 处理接收到的数据
CString receivedData(buffer, nRecvBytes);
AfxMessageBox(receivedData);

总结

        MFC Winsock 类是 MFC 框架中用于网络编程的一套类,它封装了 Windows 操作系统中的 Winsock API,为程序员提供了一套面向对象的接口来实现网络通信和数据传输。MFC Winsock 类库提供了异步和同步两种编程模型,满足了不同应用程序的需求。MFC Winsock 类广泛应用于各种 Windows 网络应用程序中,为程序员提供了强大的工具和框架,简化了网络编程的过程。

  • 22
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值