MFC 网络编程

MFC 通信简介

互联网通信基础是 TCP/IP,即传输控制协议和网络互连协议。在 TCP/IP 中计算机软件通信必须依赖于通信端口,端口号的范围是 0 ~ 65535。每个进程启动后可以申请一个或多个端口号,但在一台计算机内每个端口号同时只能被一个进程占用,否则就会造成端口冲突。


MFC 套接字简介

1.MFC 中与套接字(socket)功能有关的类包括

CAsyncSocket 类对套接字 API 进行了较低级别的封装
CSocket 类对套接字 API 进行了较高级别的封装

其中:CSocket 类是 CAsyncSocket 类的派生类

2.套接字种类

流套接字(Stream Socket)

(1)使用 TCP协议进行通信

具有 TCP 协议所拥有的各种特征,面向连接的、可靠的数据流传输服务。数据包不会出现丢失、重复、乱序等现象

(2)数据报套接字(datagram socket)

使用 UDP 协议进行通信,具有 UDP 协议所拥有的各种特征。面向非连接的、不可靠的用户数据报传输服务,数据包可能出现丢失、重复、乱序等现象。

3.套接字类函数

create:用于创建一个 Windows 套接字,并将其附加到 CAsyncSocket 类对象上

BOOL Create(UINT nSocketPort = 0,
            int nSocketType = SOCK_STREAM,
            long IEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
            LPCTSTR lpszSocketAddress = NULL
);

参数说明如下:

  • nSocketPort 
    表示套接字端口,如果为 0,系统将自动选择一个端口

  • nSocketType 
    表示套接字的类型,SOCK_STREAM表示流套接字SOCK_DGRAM表示数据报套接字。

  • lEvent 
    一个位掩码,指定应用程序能够处理的网络事件的组合。

    • FD_READ    想要收到阅读准备的通知。

    • FD_WRITE    想要收到写作准备的通知。

    • FD_OOB    想要接收带外数据到达的通知。

    • FD_ACCEPT    想要接收传入连接的通知。

    • FD_CONNECT    想要接收已完成连接的通知。

    • FD_CLOSE    想要接收套接字关闭的通知。

  • lpszSockAddress
    指向已连接套接字的网络地址的字符串的指针,虚线数字如“128.56.22.8” 。为此参数传递NULL字符串表示CAsyncSocket实例应在所有网络接口上侦听客户端活动。

GetLastError:用于获取最后一次操作失败的状态信息

static int GetLastError();

GetPeerName:用于获取套接字连接的 IP 地址信息。

BOOL GetPeerName(CString& rPeerAddress, UINT& rPeerPort);
BOOL GetPeerName(SOCKADDR* lpSockAddr, int* lpSCokAddrLen);

参数说明如下:

  • rPeerAddress 
    对接收函数返回IP地址的CString对象的引用。

  • rPeerPort 
    用于记录端口号。

  • lpSockAddr 
    指向SOCKADDR结构的指针,该结构接收对等套接字的名称。

  • lpSockAddrLen 
    指向lpSockAddr中地址长度的指针,以字节为单位。返回时,lpSockAddrLen参数包含以字节为单位返回的lpSockAddr的实际大小。

Accept:用于接收客户端的链接

virtual BOOL Accept(
   CAsyncSocket& rConnectedSocket,
   SOCKADDR* lpSockAddr = NULL,
   int* lpSockAddrLen = NULL 
);

参数说明如下:

  • rConnectedSocket 
    标识可用于连接的新套接字的引用。

  • lpSockAddr 
    指向SOCKADDR结构的指针,该结构接收连接套接字的地址,如网络上已知的那样。lpSockAddr参数的确切格式由创建套接字时建立的地址族决定。如果lpSockAddr和/或lpSockAddrLen等于NULL,则不返回有关已接受套接字的远程地址的信息。

  • lpSockAddrLen 
    指向lpSockAddr中地址长度的指针,以字节为单位。lpSockAddrLen是一个value-result参数:它应该最初包含lpSockAddr指向的空间量; 返回时,它将包含返回地址的实际长度(以字节为单位)。

Bind:用于将 IP 地址和端口号绑定到套接字上

BOOL Bind( 
   UINT nSocketPort, 
   LPCTSTR lpszSocketAddress = NULL  
); 
BOOL Bind ( 
   const SOCKADDR* lpSockAddr, 
   int nSockAddrLen  
);

参数说明如下:

  • nSocketPort 
    标识套接字应用程序的端口。

  • lpszSocketAddress 
    网络地址,点缀数如“128.56.22.8”。传递此参数的NULL字符串表示CAsyncSocket实例应侦听所有网络接口上的客户端活动。

  • lpSockAddr 
    指向SOCKADDR结构的指针,该结构包含要分配给此套接字的地址。

  • nSockAddrLen 
    lpSockAddr中地址的长度(以字节为单位)。

connect:用于发送一个链接请求

BOOL Connect( 
   LPCTSTR lpszHostAddress, 
   UINT nHostPort  
); 
BOOL Connect( 
   const SOCKADDR* lpSockAddr, 
   int nSockAddrLen  
);

参数说明如下:

  • lpszHostAddress 
    此对象所连接的套接字的网络地址:计算机名称,例如“ftp.microsoft.com”,或点号,例如“128.56.22.8”。

  • nHostPort 
    标识套接字应用程序的端口。

  • lpSockAddr 
    指向SOCKADDR结构的指针,该结构包含已连接套接字的地址。

  • nSockAddrLen 
    lpSockAddr中地址的长度(以字节为单位)。

close:用于关闭套接字

virtual void Close( );

listen:用于将套接字置于监听模式

BOOL Listen( 
   int nConnectionBacklog = 5  
);
  • nConnectionBacklog
    挂起连接队列可以增长的最大长度。有效范围是1到5。

receive:用于在流式套接字中接收数据

virtual int Receive( 
   void* lpBuf, 
   int nBufLen, 
   int nFlags = 0  
);
  • lpBuf 
    传入数据的缓冲区。

  • nBufLen lpBuf 
    的长度,以字节为单位。

  • nFlags 
    指定进行调用的方式。此函数的语义由套接字选项和nFlags参数确定。后者是通过将以下任何值与C ++ OR运算符组合而构造的:

    • MSG_PEEK    查看传入的数据。数据将复制到缓冲区中,但不会从输入队列中删除。

    • MSG_OOB    处理带外数据。

send:用于向流式套接字中发送数据

virtual int Send( 
   const void* lpBuf, 
   int nBufLen, 
   int nFlags = 0  
);
  • lpBuf 
    包含要传输的数据的缓冲区。

  • nBufLen lpBuf 
    中的数据长度,以字节为单位。

  • nFlags 
    指定进行调用的方式。此函数的语义由套接字选项和nFlags参数确定。后者是通过将以下任何值与C ++ OR运算符组合而构造的:

    • MSG_DONTROUTE    指定数据不应受路由限制。Windows套接字供应商可以选择忽略此标志。

    • MSG_OOB    发送带外数据(仅限SOCK_STREAM)。

4.套接字事件响应

OnAccept:当套接字接收链接请求时触发该事件(服务器端)

virtual void OnAccept( 
   int nErrorCode  
);
  • nErrorCode
    套接字上的最新错误。以下错误代码适用于OnAccept成员函数:

    • 0    功能执行成功。

    • WSAENETDOWN    Windows Sockets实现检测到网络子系统发生故障。

OnClose:当套接字关闭时触发该事件

virtual void OnClose( 
   int nErrorCode  
);
  • nErrorCode
    套接字上的最新错误。以下错误代码适用于OnCLose成员函数:

    • 0    功能执行成功。

    • WSAENETDOWN    Windows Sockets实现检测到网络子系统发生故障。

    • WSAECONNRESET    远程端重置了连接。

    • WSAECONNABORTED    由于超时或其他故障导致连接中止。

OnConnect:当套接字连接之后触发该事件(客户端)

virtual void OnConnect( 
   int nErrorCode  
);
  • nErrorCode
    套接字上的最新错误。以下错误代码适用于OnCnnect成员函数:

    • 0    功能执行成功。

    • WSAEADDRINUSE    指定的地址已被使用。

    • WSAEADDRNOTAVAIL    指定的地址在本地计算机上不可用。

    • WSAEAFNOSUPPORT    指定系列中的地址不能与此套接字一起使用。

    • WSAECONNREFUSED    强行拒绝连接尝试。

    • WSAEDESTADDRREQ    需要目标地址。

    • WSAEFAULT    lpSockAddrLen参数不正确。

    • WSAEINVAL    套接字已绑定到某个地址。

    • WSAEISCONN     套接字已连接。

    • WSAEMFILE    没有更多文件描述符可用。

    • WSAENETUNREACH    此时无法从此主机访问网络。

    • WSAENOBUFS    没有可用的缓冲区空间。插座无法连接。

    • WSAENOTCONN    套接字未连接。

    • WSAENOTSOCK    描述符是一个文件,而不是套接字。

    • WSAETIMEDOUT    尝试在没有建立连接的情况下连接超时。

OnReceive:当套接字上有数据被接收时触发该事件

virtual void OnReceive( 
   int nErrorCode  
);
  • nErrorCode
    套接字上的最新错误。以下错误代码适用于OnReceive成员函数:

    • 0    功能执行成功。

    • WSAENETDOWN    Windows Sockets实现检测到网络子系统发生故障。

OnSend:当套接字发送数据时触发该消息

virtual void OnSend( 
   int nErrorCode  
);
  • nErrorCode
    套接字上的最新错误。以下错误代码适用于OnSend成员函数:

    • 0    功能执行成功。

    • WSAENETDOWN    Windows Sockets实现检测到网络子系统发生故障。

更多详细解释请参考 MSDN : https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2008/09353w3t(v%3dvs.90)


MFC 通信

1.通信前的准备

①客户端调用 connect 函数以连接到服务器

②服务器端调用 listen 函数以监听客户的进入

③服务器端调用 accept 函数与客户建立连接

2.收发数据

流套接字发送数据:Send

流套接字接收数据:Receive

3.C/S模型

遇到的问题:

1.客户端无法连接服务器

答:

①检查服务器是否正常运行

②客户端IP 和端口是否配置正常,是否和服务器 IP 和端口一致

③在IP 和端口配置正确情况下,考虑错误发生在跨网段通信。

首先 cmd 打开控制台,ping 服务器的 IP 地址,如果 ping通则说明问题不在此,如果没 ping 通则问题出在此处,需要将两台电脑 IP 运行在同一网段上。

④分别在服务器端accept 和客户端 connect 设置断点,检查错误发生在服务器端还是客户端。如果发生在 connect 处,则调用WSAGetLastError函数:https://docs.microsoft.com/en-us/windows/desktop/api/winsock/nf-winsock-wsagetlasterror#syntax  (这个链接里有详细用法及错误返回码解释)
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值