表示 Windows 套接字 - 网络通信终结点。
语法
class CAsyncSocket : public CObject
成员
公共构造函数
| 名称 | 描述 |
|---|---|
CAsyncSocket::CAsyncSocket |
构造 CAsyncSocket 对象。 |
公共方法
受保护方法
| 名称 | 描述 |
|---|---|
CAsyncSocket::OnAccept |
通知侦听套接字,它可以通过调用 Accept 来接受挂起的连接请求。 |
CAsyncSocket::OnClose |
通知套接字,连接到它的套接字已关闭。 |
CAsyncSocket::OnConnect |
通知连接套接字,连接尝试已完成,无论是成功还是出错。 |
CAsyncSocket::OnOutOfBandData |
通知接收套接字,套接字上有要读取的带外数据(通常是紧急消息)。 |
CAsyncSocket::OnReceive |
通知侦听套接字,有要通过调用 Receive 来检索的数据。 |
CAsyncSocket::OnSend |
通知套接字,它可以通过调用 Send 来发送数据。 |
公共运算符
| 名称 | 描述 |
|---|---|
| CAsyncSocket::operator = | 为 CAsyncSocket 对象分配新值。 |
| CAsyncSocket::operator SOCKET | 使用此运算符检索 SOCKET 对象的 CAsyncSocket 句柄。 |
公共数据成员
| 名称 | 描述 |
|---|---|
CAsyncSocket::m_hSocket |
指示附加到此 SOCKET 对象的 CAsyncSocket 句柄。 |
备注
类 CAsyncSocket 封装 Windows 套接字函数 API,为想要将 Windows 套接字与 MFC 结合使用的程序员提供面向对象的抽象。
此类基于这样一个假设:你了解网络通信。 你负责处理 Unicode 和多字节字符集 (MBCS) 字符串之间的阻塞、字节顺序差异和转换。 如果你想要一个更方便的界面来为自己管理这些问题,请参阅类 CSocket。
若要使用 CAsyncSocket 对象,请调用其构造函数,然后调用 Create 函数来创建基础套接字句柄(类型 SOCKET),但这不包括已接受的套接字上的情况。 为服务器套接字调用 Listen 成员函数,为客户端套接字调用 Connect 成员函数。 收到连接请求时,服务器套接字应调用 Accept 函数。 使用其余的 CAsyncSocket 函数在套接字之间进行通信。 完成后,如果已在堆上创建 CAsyncSocket 对象,则销毁该对象;析构函数会自动调用 Close 函数。
SOCKET一文中介绍了 数据类型。
注意
在静态链接的 MFC 应用程序中的辅助线程中使用 MFC 套接字时,您必须在使用套接字的每个线程中调用 AfxSocketInit 来初始化套接字库。 默认情况下,仅在主线程中调用 AfxSocketInit。
有关详细信息,请参阅 Windows 套接字:使用类 CAsyncSocket 和相关文章,以及 Windows 套接字 2 API。
继承层次结构
CAsyncSocket
要求
标头:afxsock.h
CAsyncSocket::Accept
调用此成员函数以接受套接字上的连接。
virtual BOOL Accept(
CAsyncSocket& rConnectedSocket,
SOCKADDR* lpSockAddr = NULL,
int* lpSockAddrLen = NULL);
参数
rConnectedSocket
一个引用,标识可用于连接的新套接字。
lpSockAddr
一个指向 SOCKADDR 结构的指针,该结构接收连接套接字的地址,如网络上所知的那样。
lpSockAddr 参数的确切格式取决于创建套接字时建立的地址系列。 如果 lpSockAddr 和/或 lpSockAddrLen 等于 NULL,则不会返回有关已接受套接字的远程地址的信息。
lpSockAddrLen
一个指针,指向 lpSockAddr 中的地址的长度(以字节为单位)。
lpSockAddrLen 是一个值-结果参数:它最初应包含 lpSockAddr 所指向的空间量;返回时,它将包含返回的地址的实际长度(以字节为单位)。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数太小(小于SOCKADDR结构的大小)。WSAEINPROGRESS:正在执行阻止型 Windows 套接字调用。WSAEINVALListen未在接受之前调用。WSAEMFILE:在进入后准备接受时,队列为空,没有可用的描述符。WSAENOBUFS:未提供任何缓冲区空间。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPP:引用的套接字不是支持面向连接的服务的类型。WSAEWOULDBLOCK:套接字标记为非阻止,没有要接受的连接。
备注
此例程提取挂起连接队列中的第一个连接,创建与此套接字具有相同属性的新套接字,并将其附加到 rConnectedSocket。 如果队列中不存在挂起的连接,则 Accept 会返回零,GetLastError 会返回错误。 接受的套接字 (rConnectedSocket) 不能用于接受更多连接。 原始套接字保持打开和侦听状态。
参数 lpSockAddr 是用连接套接字的地址填充的结果参数,对通信层来说为已知。
Accept 与基于连接的套接字类型(例如 SOCK_STREAM)配合使用。
CAsyncSocket::AsyncSelect
调用此成员函数可请求套接字的事件通知。
BOOL AsyncSelect(long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
参数
lEvent
位掩码,指定应用程序感兴趣的网络事件的组合。
FD_READ:想要接收准备读取的通知。FD_WRITE:想要在数据可供读取时接收通知。FD_OOB:想要接收带外数据的到达通知。FD_ACCEPT:想要接收传入连接的通知。FD_CONNECT:想要接收连接结果的通知。FD_CLOSE:想要在对等机关闭套接字时接收通知。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEINVAL:指示指定参数之一无效。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。
备注
此函数用于指定将针对套接字调用哪个 MFC 回调通知函数。
AsyncSelect 自动将此套接字设置为非阻止模式。 有关详细信息,请参阅 Windows 套接字:套接字通知一文。
CAsyncSocket::Attach
调用此成员函数以将 hSocket 句柄附加到 CAsyncSocket 对象。
BOOL Attach(
SOCKET hSocket, long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
参数
hSocket
包含套接字的句柄。
lEvent
位掩码,指定应用程序感兴趣的网络事件的组合。
FD_READ:想要接收准备读取的通知。FD_WRITE:想要在数据可供读取时接收通知。FD_OOB:想要接收带外数据的到达通知。FD_ACCEPT:想要接收传入连接的通知。FD_CONNECT:想要接收连接结果的通知。FD_CLOSE:想要在对等机关闭套接字时接收通知。
返回值
如果函数运行成功,则为非零。
备注
SOCKET 句柄存储在对象的 m_hSocket 数据成员中。
CAsyncSocket::Bind
调用此成员函数以将本地地址与套接字相关联。
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 中的地址的长度(以字节为单位)。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下列表涵盖可能返回的一些错误。 有关完整列表,请参阅 Windows 套接字错误代码。
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEADDRINUSE:指定的地址已被使用。 (请参阅SO_REUSEADDR下的SetSockOpt套接字选项。)WSAEFAULT:nSockAddrLen参数太小(小于SOCKADDR结构的大小)。WSAEINPROGRESS:正在执行阻止型 Windows 套接字调用。WSAEAFNOSUPPORT:此端口不支持指定的地址系列。WSAEINVAL:套接字已绑定到地址。WSAENOBUFS:没有足够的缓冲区可用,连接过多。WSAENOTSOCK:描述符不是套接字。
备注
在进行后续的 Connect 或 Listen 调用之前,此例程在未连接的数据报或流套接字上使用。 在它接受连接请求之前,侦听服务器套接字必须选择端口号,并通过调用 Bind 使 Windows 套接字知道它。
Bind 通过将本地名称分配给未命名的套接字来建立套接字的本地关联(主机地址/端口号)。
CAsyncSocket::CAsyncSocket
构造空白套接字对象。
CAsyncSocket();
备注
构造对象后,必须调用其 Create 成员函数来创建 SOCKET 数据结构并绑定其地址。 (在 Windows 套接字通信的服务器端,当侦听套接字创建用于 Accept 调用的套接字时,请勿为该套接字调用 Create。)
CAsyncSocket::Close
关闭套接字。
virtual void Close();
备注
此函数释放套接字描述符,因此对它的进一步引用会失败并出现错误 WSAENOTSOCK。 如果这是对基础套接字的最后一个引用,则会丢弃关联的命名信息和排队的数据。 套接字对象的析构函数会为你调用 Close。
CAsyncSocket 的语义受套接字选项 CSocket 和 Close 的影响,这适用于 SO_LINGER,但不适用于 SO_DONTLINGER。 有关详细信息,请参阅成员函数 GetSockOpt。
CAsyncSocket::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 中的地址的长度(以字节为单位)。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 如果这指示错误代码 WSAEWOULDBLOCK,并且应用程序正在使用可重写回调,则当连接操作完成时,应用程序会收到一条 OnConnect 消息。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEADDRINUSE:指定的地址已被使用。WSAEINPROGRESS:正在执行阻止型 Windows 套接字调用。WSAEADDRNOTAVAIL:指定的地址不能从本地计算机使用。WSAEAFNOSUPPORT:指定的系列中的地址无法与此套接字配合使用。WSAECONNREFUSED:连接尝试被拒绝。WSAEDESTADDRREQ:需要目标地址。WSAEFAULT:nSockAddrLen参数不正确。WSAEINVAL:主机地址无效。WSAEISCONN:套接字已连接。WSAEMFILE:没有更多可用的文件描述符。WSAENETUNREACH:此时不可从此主机访问该网络。WSAENOBUFS:未提供任何缓冲区空间。 无法连接套接字。WSAENOTSOCK:描述符不是套接字。WSAETIMEDOUT:连接尝试超时,没有建立连接。WSAEWOULDBLOCK:套接字标记为非阻止,无法立即完成连接。
备注
如果套接字未绑定,则系统会将唯一值分配给本地关联,该套接字会被标记为已绑定。 请注意,如果名称结构的地址字段全为零,Connect 会返回零。 若要获得扩展的错误信息,请调用 GetLastError 成员函数。
对于流套接字(类型为 SOCK_STREAM),将启动到外部主机的活动连接。 套接字调用成功完成后,该套接字就可以发送/接收数据了。
对于数据报套接字(类型为 SOCK_DGRAM),将设置默认目标,该目标将在进行后续的 Send 和 Receive 调用时使用。
CAsyncSocket::Create
构造套接字对象后调用 Create 成员函数以创建 Windows 套接字并附加它。
BOOL Create(
UINT nSocketPort = 0,
int nSocketType = SOCK_STREAM,
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
LPCTSTR lpszSocketAddress = NULL);
参数
nSocketPort
要与套接字一起使用的已知端口,或 0(如果希望 Windows 套接字选择某个端口)。
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 实例应侦听所有网络接口上的客户端活动。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEAFNOSUPPORT:不支持指定的地址系列。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEMFILE:没有更多可用的文件描述符。WSAENOBUFS:未提供任何缓冲区空间。 无法创建套接字。WSAEPROTONOSUPPORT:不支持指定的端口。WSAEPROTOTYPE:指定的端口是此套接字的错误类型。WSAESOCKTNOSUPPORT:在此地址系列中,不支持指定的套接字类型。
备注
Create 调用 Socket,如果成功,它会调用 Bind 以将套接字绑定到指定地址。 支持以下套接字类型:
SOCK_STREAM:提供有序、可靠、全双工、基于连接的字节流。 使用 Internet 地址系列的传输控制协议 (TCP)。SOCK_DGRAM:支持数据报,即最大长度(通常很小)固定的无连接、不可靠数据包。 对 Internet 地址系列使用用户数据报协议 (UDP)。注意
Accept成员函数会引用一个新的空CSocket对象作为其参数。 必须先构造此对象,然后才能调用Accept。 请记住,如果此套接字对象超出范围,则会关闭连接。 请勿为此新的套接字对象调用Create。
重要
Create 不是线程安全型。 如果要在多线程环境中调用它(可在其中由不同线程同时调用它),请务必使用互斥锁或其他同步锁保护每个调用。
有关流和数据报套接字的更多信息,请参阅以下文章:Windows 套接字:背景、Windows 套接字:端口和套接字地址和 Windows 套接字 2 API。
CAsyncSocket::CreateEx
构造套接字对象后调用 CreateEx 成员函数以创建 Windows 套接字并附加它。
如果需要提供高级选项(如套接字类型),请使用此函数。
BOOL CreateEx(
ADDRINFOT* pAI,
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE);
参数
pAI
一个指针,指向用于保存套接字信息(如系列和套接字类型)的 ADDRINFOT。
lEvent
位掩码,指定应用程序感兴趣的网络事件的组合。
FD_READ:想要接收准备读取的通知。FD_WRITE:想要接收准备写入的通知。FD_OOB:想要接收带外数据的到达通知。FD_ACCEPT:想要接收传入连接的通知。FD_CONNECT:想要接收已完成连接的通知。FD_CLOSE:想要接收套接字关闭的通知。
返回值
请查看 Create() 的返回值。
备注
请参见 Create() 的注解。
CAsyncSocket::Detach
调用此成员函数可从 SOCKET 对象中拆离 m_hSocket 数据成员中的 CAsyncSocket 句柄并将 m_hSocket 设置为 NULL。
SOCKET Detach();
CAsyncSocket::FromHandle
返回一个指向 CAsyncSocket 对象的指针。
static CAsyncSocket* PASCAL FromHandle(SOCKET hSocket);
参数
hSocket
包含套接字的句柄。
返回值
指向 CAsyncSocket 对象的指针,或者 NULL(如果没有附加到 CAsyncSocket 的 hSocket 对象)。
备注
给定 SOCKET 句柄时,如果 CAsyncSocket 对象未附加到该句柄,成员函数会返回 NULL。
CAsyncSocket::GetLastError
调用此成员函数可获取上次失败操作的错误状态。
static int PASCAL GetLastError();
返回值
返回值指示此线程执行的最后一个 Windows 套接字 API 例程的错误代码。
备注
当特定成员函数指示发生了错误时,应调用 GetLastError 来检索相应的错误代码。 有关相应错误代码的列表,请参阅各个成员函数说明。
有关错误代码的详细信息,请参阅 Windows 套接字 2 API。
CAsyncSocket::GetPeerName
调用此成员函数可获取此套接字连接到的对等机套接字的地址。
BOOL GetPeerName(
CString& rPeerAddress,
UINT& rPeerPort);
BOOL GetPeerName(
SOCKADDR* lpSockAddr,
int* lpSockAddrLen);
参数
rPeerAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rPeerPort
对存储端口的 UINT 的引用。
lpSockAddr
一个指向 SOCKADDR 结构的指针,该结构接收对等机套接字的名称。
lpSockAddrLen
一个指针,指向 lpSockAddr 中的地址的长度(以字节为单位)。 返回时,lpSockAddrLen 参数包含返回的 lpSockAddr 的实际大小(以字节为单位)。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数不够大。WSAEINPROGRESS:正在执行阻止型 Windows 套接字调用。WSAENOTCONN:套接字未连接。WSAENOTSOCK:描述符不是套接字。
备注
若要处理 IPv6 地址,请使用 CAsyncSocket::GetPeerNameEx。
CAsyncSocket::GetPeerNameEx
调用此成员函数可获取此套接字连接到的对等机套接字的地址(处理 IPv6 地址)。
BOOL GetPeerNameEx(
CString& rPeerAddress,
UINT& rPeerPort);
参数
rPeerAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rPeerPort
对存储端口的 UINT 的引用。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数不够大。WSAEINPROGRESS:正在执行阻止型 Windows 套接字调用。WSAENOTCONN:套接字未连接。WSAENOTSOCK:描述符不是套接字。
备注
此函数与 CAsyncSocket::GetPeerName 相同,只是它处理 IPv6 地址和较旧的协议。
CAsyncSocket::GetSockName
调用此成员函数可获取套接字的本地名称。
BOOL GetSockName(
CString& rSocketAddress,
UINT& rSocketPort);
BOOL GetSockName(
SOCKADDR* lpSockAddr,
int* lpSockAddrLen);
参数
rSocketAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rSocketPort
对存储端口的 UINT 的引用。
lpSockAddr
一个指向 SOCKADDR 结构的指针,该结构接收套接字的地址。
lpSockAddrLen
一个指针,指向 lpSockAddr 中的地址的长度(以字节为单位)。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数不够大。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOTSOCK:描述符不是套接字。WSAEINVAL:尚未使用Bind将套接字绑定到某个地址。
备注
在未先执行 Connect 的情况下进行 Bind 调用时,此调用尤其有用;此调用提供唯一的方法来确定已由系统设置的本地关联。
若要处理 IPv6 地址,请使用 CAsyncSocket::GetSockNameEx
CAsyncSocket::GetSockNameEx
调用此成员函数可获取套接字的本地名称(处理 IPv6 地址)。
BOOL GetSockNameEx(
CString& rSocketAddress,
UINT& rSocketPort);
参数
rSocketAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rSocketPort
对存储端口的 UINT 的引用。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数不够大。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOTSOCK:描述符不是套接字。WSAEINVAL:尚未使用Bind将套接字绑定到某个地址。
备注
此调用与 CAsyncSocket::GetSockName 相同,只是它处理 IPv6 地址和较旧的协议。
在未先执行 Connect 的情况下进行 Bind 调用时,此调用尤其有用;此调用提供唯一的方法来确定已由系统设置的本地关联。
CAsyncSocket::GetSockOpt
调用此成员函数可检索套接字选项。
BOOL GetSockOpt(
int nOptionName,
void* lpOptionValue,
int* lpOptionLen,
int nLevel = SOL_SOCKET);
参数
nOptionName
要为其检索值的套接字选项。
lpOptionValue
一个指向缓冲区的指针,在该缓冲区中,将返回所请求的选项的值。 与所选选项关联的值在缓冲区 lpOptionValue 中返回。
lpOptionLen 所指向的整数最初应包含此缓冲区的大小(以字节为单位);返回时,会将它设置为返回的值的大小。 对于 SO_LINGER,这将是 LINGER 结构的大小;对于所有其他选项,它将是 BOOL 或 int 的大小,具体取决于选项。 请参阅“注解”部分的选项及其大小的列表。
lpOptionLen
一个指针,指向 lpOptionValue 缓冲区的大小(以字节为单位)。
nLevel
定义选项时所在的级别;唯一受支持的级别是 SOL_SOCKET 和 IPPROTO_TCP。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 如果从未使用 SetSockOpt 设置某个选项,则 GetSockOpt 会返回该选项的默认值。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpOptionLen参数无效。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOPROTOOPT:选项未知或不受支持。 具体而言,SO_BROADCAST在类型为SOCK_STREAM的套接字上不受支持,而SO_ACCEPTCONN、SO_DONTLINGER、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE在类型为SOCK_DGRAM的套接字上不受支持。WSAENOTSOCK:描述符不是套接字。
备注
GetSockOpt 检索与任何类型、任何状态的套接字关联的套接字选项的当前值,并将结果存储在 lpOptionValue 中。 选项会影响套接字操作,例如数据包路由、带外数据传输等。
GetSockOpt 支持以下选项。 “类型”标识 lpOptionValue 所寻址的数据的类型。
TCP_NODELAY 选项使用级别 IPPROTO_TCP;所有其他选项都使用级别 SOL_SOCKET。
| 值 | 类型 | 含义 |
|---|---|---|
SO_ACCEPTCONN |
BOOL |
套接字正在侦听。 |
SO_BROADCAST |
BOOL |
配置套接字是为了传输广播消息。 |
SO_DEBUG |
BOOL |
已启用调试。 |
SO_DONTLINGER |
BOOL |
如果为 true,则禁用 SO_LINGER 选项。 |
SO_DONTROUTE |
BOOL |
路由功能被禁用。 |
SO_ERROR |
int |
检索错误状态并进行清除。 |
SO_KEEPALIVE |
BOOL |
正在发送“保持连接”。 |
SO_LINGER |
struct LINGER |
返回当前的逗留选项。 |
SO_OOBINLINE |
BOOL |
正在正常数据流中接收带外数据。 |
SO_RCVBUF |
int |
接收操作的缓冲区大小。 |
SO_REUSEADDR |
BOOL |
可以将套接字绑定到已在使用中的地址。 |
SO_SNDBUF |
int |
发送操作的缓冲区大小。 |
SO_TYPE |
int |
套接字的类型(例如 SOCK_STREAM)。 |
TCP_NODELAY |
BOOL |
为发送合并禁用 Nagle 算法。 |
GetSockOpt 不支持的伯克利软件发行版 (BSD) 选项如下:
| 值 | 类型 | 含义 |
|---|---|---|
SO_RCVLOWAT |
int |
接收低水印。 |
SO_RCVTIMEO |
int |
接收超时。 |
SO_SNDLOWAT |
int |
发送低水印。 |
SO_SNDTIMEO |
int |
发送超时。 |
IP_OPTIONS |
获取 IP 标头中的选项。 | |
TCP_MAXSEG |
int |
获取 TCP 最大片段大小。 |
使用不受支持的选项调用 GetSockOpt 会导致从 WSAENOPROTOOPT 返回错误代码 GetLastError。
CAsyncSocket::IOCtl
调用此成员函数可控制套接字的模式。
BOOL IOCtl(
long lCommand,
DWORD* lpArgument);
参数
lCommand
要在套接字上执行的命令。
lpArgument
一个指向 lCommand 的参数的指针。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEINVALlCommand不是有效的命令,或者lpArgument不是可接受的参数lCommand,或者该命令不适用于提供的套接字类型。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOTSOCK:描述符不是套接字。
备注
此例程可用在任何状态的任何套接字上。 它用于获取或检索与套接字关联的操作参数,独立于协议和通信子系统。 支持以下命令:
FIONBIO:在套接字上启用或禁用非阻止模式。lpArgument参数指向一个DWORD,后者在要启用非阻止模式的情况下为非零值,在要禁用非阻止模式的情况下为零。 如果已在套接字上颁发AsyncSelect,则使用IOCtl将套接字重新设置为阻止模式的任何尝试都会失败,并出现WSAEINVAL错误。 若要将套接字重新设置为阻止模式并防止WSAEINVAL错误,应用程序必须先通过在AsyncSelect参数等于 0 的情况下调用AsyncSelect来禁用lEvent,然后调用IOCtl。FIONREAD:确定可通过一次从此套接字进行的Receive调用读取的最大字节数。lpArgument参数指向DWORD,IOCtl在其中存储结果。 如果此套接字的类型为SOCK_STREAM,则FIONREAD会返回可在单个Receive中读取的数据总量;这通常与在套接字上排队的数据总量相同。 如果此套接字的类型为SOCK_DGRAM,则FIONREAD会返回在套接字上排队的第一个数据报的大小。SIOCATMARK:确定是否已读取所有带外数据。 这仅适用于已配置为对任何带外数据进行内联接收的SOCK_STREAM套接字(SO_OOBINLINE)。 如果没有任何带外数据在等待读取,则操作会返回非零值。 否则,操作会返回 0,并且对套接字执行的下一个Receive或ReceiveFrom会检索“mark”之前的部分或全部数据;应用程序应使用SIOCATMARK操作来确定是否还有剩余数据。 如果在“紧急”(带外)数据之前有任何正常数据,则会按顺序接收它。 (请注意,在同一调用中,Receive或ReceiveFrom永远不会混合使用带外数据和正常数据。)lpArgument参数指向DWORD,IOCtl在其中存储结果。
此函数是 ioctl() 的子集,正如伯克利套接字中使用的那样。 具体而言,没有等效于 FIOASYNC 的命令,而 SIOCATMARK 是唯一受支持的套接字级命令。
CAsyncSocket::Listen
调用此成员函数以侦听传入的连接请求。
BOOL Listen(int nConnectionBacklog = 5);
参数
nConnectionBacklog
挂起连接的队列可以增长到的最大长度。 有效范围为 1 到 5。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEADDRINUSE:已尝试在在已使用的地址上进行侦听。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEINVAL:套接字尚未使用Bind进行绑定或已连接。WSAEISCONN:套接字已连接。WSAEMFILE:没有更多可用的文件描述符。WSAENOBUFS:未提供任何缓冲区空间。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPP:引用的套接字不是支持Listen操作的类型。
备注
若要接受连接,请首先使用 Create 创建套接字,接着使用 Listen 指定传入连接的积压工作 (backlog),然后使用 Accept 接受连接。
Listen 仅适用于支持连接的套接字,即类型为 SOCK_STREAM 的套接字。 此套接字会置于“被动”模式,在此模式中,传入连接在获得确认后会排队等待进程接受。
此函数通常由服务器(或任何想要接受连接的应用程序)使用,这些服务器或应用程序可能一次有多个连接请求:如果连接请求到达时队列已满,则客户端会收到一个指示 WSAECONNREFUSED 的错误。
Listen 在没有可用端口(描述符)时会尝试继续合理运行。 它将接受连接,直到队列被清空。 如果端口变得可用,则以后调用 Listen 或 Accept 时会尽可能使用当前的或最新的“积压工作”来重新填充队列,并恢复对传入连接的侦听。
CAsyncSocket::m_hSocket
包含此 SOCKET 对象封装的套接字的 CAsyncSocket 句柄。
SOCKET m_hSocket;
CAsyncSocket::OnAccept
由框架调用,用于通知侦听套接字:它可以通过调用 Accept 成员函数来接受挂起的连接请求。
virtual void OnAccept(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnAccept 成员函数:
0:函数已成功执行。
WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。
备注
有关详细信息,请参阅 Windows 套接字:套接字通知。
CAsyncSocket::OnClose
由框架调用,用于通知此套接字:连接的套接字是由其进程关闭的。
virtual void OnClose(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnClose 成员函数:
0:函数已成功执行。
WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAECONNRESET:此连接已由远端重置。WSAECONNABORTED:由于超时或其他故障,连接已中止。
备注
有关详细信息,请参阅 Windows 套接字:套接字通知。
CAsyncSocket::OnConnect
由框架调用,用于通知此连接套接字:其连接尝试已完成(无论是成功还是出错)。
virtual void OnConnect(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnConnect 成员函数:
0:函数已成功执行。
WSAEADDRINUSE:指定的地址已被使用。WSAEADDRNOTAVAIL:指定的地址不能从本地计算机使用。WSAEAFNOSUPPORT:指定的系列中的地址无法与此套接字配合使用。WSAECONNREFUSED:连接尝试被强制性拒绝。WSAEDESTADDRREQ:需要目标地址。WSAEFAULT:lpSockAddrLen参数不正确。WSAEINVAL:套接字已绑定到地址。WSAEISCONN:套接字已连接。WSAEMFILE:没有更多可用的文件描述符。WSAENETUNREACH:此时不可从此主机访问该网络。WSAENOBUFS:未提供任何缓冲区空间。 无法连接套接字。WSAENOTCONN:套接字未连接。WSAENOTSOCK:描述符是文件,而不是套接字。WSAETIMEDOUT:连接尝试超时,没有建立连接。
备注
注意
在 CSocket 中,从不调用 OnConnect 通知函数。 对于连接,请直接调用 Connect,它会在连接完成时(不管是成功还是出错)返回信息。 如何处理连接通知取决于 MFC 实现细节。
有关详细信息,请参阅 Windows 套接字:套接字通知。
示例
void CMyAsyncSocket::OnConnect(int nErrorCode) // CMyAsyncSocket is
// derived from CAsyncSocket
{
if (0 != nErrorCode)
{
switch (nErrorCode)
{
case WSAEADDRINUSE:
AfxMessageBox(_T("The specified address is already in use.\n"));
break;
case WSAEADDRNOTAVAIL:
AfxMessageBox(_T("The specified address is not available from ")
_T("the local machine.\n"));
break;
case WSAEAFNOSUPPORT:
AfxMessageBox(_T("Addresses in the specified family cannot be ")
_T("used with this socket.\n"));
break;
case WSAECONNREFUSED:
AfxMessageBox(_T("The attempt to connect was forcefully rejected.\n"));
break;
case WSAEDESTADDRREQ:
AfxMessageBox(_T("A destination address is required.\n"));
break;
case WSAEFAULT:
AfxMessageBox(_T("The lpSockAddrLen argument is incorrect.\n"));
break;
case WSAEINVAL:
AfxMessageBox(_T("The socket is already bound to an address.\n"));
break;
case WSAEISCONN:
AfxMessageBox(_T("The socket is already connected.\n"));
break;
case WSAEMFILE:
AfxMessageBox(_T("No more file descriptors are available.\n"));
break;
case WSAENETUNREACH:
AfxMessageBox(_T("The network cannot be reached from this host ")
_T("at this time.\n"));
break;
case WSAENOBUFS:
AfxMessageBox(_T("No buffer space is available. The socket ")
_T("cannot be connected.\n"));
break;
case WSAENOTCONN:
AfxMessageBox(_T("The socket is not connected.\n"));
break;
case WSAENOTSOCK:
AfxMessageBox(_T("The descriptor is a file, not a socket.\n"));
break;
case WSAETIMEDOUT:
AfxMessageBox(_T("The attempt to connect timed out without ")
_T("establishing a connection. \n"));
break;
default:
TCHAR szError[256];
_stprintf_s(szError, _T("OnConnect error: %d"), nErrorCode);
AfxMessageBox(szError);
break;
}
AfxMessageBox(_T("Please close the application"));
}
CAsyncSocket::OnConnect(nErrorCode);
}
CAsyncSocket::OnOutOfBandData
由框架调用,用于通知接收套接字:发送套接字有要发送的带外数据。
virtual void OnOutOfBandData(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnOutOfBandData 成员函数:
0:函数已成功执行。
WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。
备注
带外数据是一个逻辑上独立的通道,它与每对类型为 SOCK_STREAM 的已连接套接字相关联。 该通道通常用于发送紧急数据。
MFC 支持带外数据,但我们不建议 CAsyncSocket 类用户使用它。 最简单的方法是创建另一个用于传递此类数据的套接字。 有关带外数据的详细信息,请参阅 Windows 套接字:套接字通知。
CAsyncSocket::OnReceive
由框架调用,用于通知此套接字:缓冲区中存在可以通过调用 Receive 成员函数进行检索的数据。
virtual void OnReceive(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnReceive 成员函数:
0:函数已成功执行。
WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。
备注
有关详细信息,请参阅 Windows 套接字:套接字通知。
示例
void CMyAsyncSocket::OnReceive(int nErrorCode) // CMyAsyncSocket is
// derived from CAsyncSocket
{
static int i = 0;
i++;
TCHAR buff[4096];
int nRead;
nRead = Receive(buff, 4096);
switch (nRead)
{
case 0:
Close();
break;
case SOCKET_ERROR:
if (GetLastError() != WSAEWOULDBLOCK)
{
AfxMessageBox(_T("Error occurred"));
Close();
}
break;
default:
buff[nRead] = _T('\0'); //terminate the string
CString szTemp(buff);
m_strRecv += szTemp; // m_strRecv is a CString declared
// in CMyAsyncSocket
if (szTemp.CompareNoCase(_T("bye")) == 0)
{
ShutDown();
s_eventDone.SetEvent();
}
}
CAsyncSocket::OnReceive(nErrorCode);
}
CAsyncSocket::OnSend
由框架调用,用于通知套接字:它现在可以通过调用 Send 成员函数发送数据。
virtual void OnSend(int nErrorCode);
参数
nErrorCode
套接字上的最新错误。 以下错误代码适用于 OnSend 成员函数:
0:函数已成功执行。
WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。
备注
有关详细信息,请参阅 Windows 套接字:套接字通知。
示例
// CMyAsyncSocket is derived from CAsyncSocket and defines the
// following variables:
// CString m_sendBuffer; //for async send
// int m_nBytesSent;
// int m_nBytesBufferSize;
void CMyAsyncSocket::OnSend(int nErrorCode)
{
while (m_nBytesSent < m_nBytesBufferSize)
{
int dwBytes;
if ((dwBytes = Send((LPCTSTR)m_sendBuffer + m_nBytesSent,
m_nBytesBufferSize - m_nBytesSent)) == SOCKET_ERROR)
{
if (GetLastError() == WSAEWOULDBLOCK)
{
break;
}
else
{
TCHAR szError[256];
_stprintf_s(szError, _T("Server Socket failed to send: %d"),
GetLastError());
Close();
AfxMessageBox(szError);
}
}
else
{
m_nBytesSent += dwBytes;
}
}
if (m_nBytesSent == m_nBytesBufferSize)
{
m_nBytesSent = m_nBytesBufferSize = 0;
m_sendBuffer = _T("");
}
CAsyncSocket::OnSend(nErrorCode);
}
CAsyncSocket::operator =
为 CAsyncSocket 对象分配新值。
void operator=(const CAsyncSocket& rSrc);
参数
rSrc
对现有 CAsyncSocket 对象的引用。
备注
调用此函数可将现有 CAsyncSocket 对象复制到另一个 CAsyncSocket 对象。
CAsyncSocket::operator SOCKET
使用此运算符检索 SOCKET 对象的 CAsyncSocket 句柄。
operator SOCKET() const;
返回值
如果成功,则为 SOCKET 对象的句柄;否则为 NULL。
备注
可以使用句柄直接调用 Windows API。
CAsyncSocket::Receive
调用此成员函数可从套接字接收数据。
virtual int Receive(
void* lpBuf,
int nBufLen,
int nFlags = 0);
参数
lpBuf
传入数据的缓冲区。
nBufLen
lpBuf 的长度(以字节为单位)。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_PEEK:速览传入数据。 数据会复制到缓冲区中,但不会从输入队列中删除。MSG_OOB:处理带外数据。
返回值
如果未发生错误,Receive 会返回收到的字节数。 如果连接已关闭,则会返回 0。 否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAENOTCONN:套接字未连接。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将Receive设置为 0 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,Receive操作会进行阻止。WSAEMSGSIZE:数据报太大,无法放入指定的缓冲区,因此被截断。WSAEINVAL:尚未使用Bind绑定套接字。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。
备注
此函数用于连接的流或数据报套接字,用于读取传入数据。
对于类型为 SOCK_STREAM 的套接字,将会返回当前可用的信息,最高信息量为提供的缓冲区的大小。 如果已将套接字配置为以内联方式接收带外数据(套接字选项 SO_OOBINLINE)且带外数据为未读,则仅返回带外数据。 应用程序可以使用 IOCtlSIOCATMARK 选项或 OnOutOfBandData 来确定是否要读取更多带外数据。
对于数据报套接字,数据将从第一个排队的数据报中提取,最大大小为提供的缓冲区大小。 如果数据报大于提供的缓冲区,则会为缓冲区填充数据报的第一部分,多余的数据会丢失。Receive 会返回值 SOCKET_ERROR,错误代码设置为 WSAEMSGSIZE。 如果套接字上没有可用的传入数据,则会返回值 SOCKET_ERROR,错误代码设置为 WSAEWOULDBLOCK。
OnReceive 回调函数可用于确定何时会有更多数据到达。
如果套接字的类型为 SOCK_STREAM,且远端已正常关闭连接,则 Receive 会立即完成,接收的字节数为 0。 如果连接已重置,则 Receive 会失败并显示错误 WSAECONNRESET。
每次调用 Receive 时,应只调用 CAsyncSocket::OnReceive 一次。
示例
请参阅 CAsyncSocket::OnReceive 的示例。
CAsyncSocket::ReceiveFrom
调用此成员函数可接收数据报并将源地址存储在 SOCKADDR 结构或 rSocketAddress 中。
int ReceiveFrom(
void* lpBuf,
int nBufLen,
CString& rSocketAddress,
UINT& rSocketPort,
int nFlags = 0);
int ReceiveFrom(
void* lpBuf,
int nBufLen,
SOCKADDR* lpSockAddr,
int* lpSockAddrLen,
int nFlags = 0);
参数
lpBuf
传入数据的缓冲区。
nBufLen
lpBuf 的长度(以字节为单位)。
rSocketAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rSocketPort
对存储端口的 UINT 的引用。
lpSockAddr
一个指向 SOCKADDR 结构的指针,该结构保存返回时获得的源地址。
lpSockAddrLen
一个指针,指向 lpSockAddr 中的源地址的长度(以字节为单位)。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_PEEK:速览传入数据。 数据会复制到缓冲区中,但不会从输入队列中删除。MSG_OOB:处理带外数据。
返回值
如果未发生错误,ReceiveFrom 会返回收到的字节数。 如果连接已关闭,则会返回 0。 否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数无效:lpSockAddr缓冲区太小,无法容纳对等机地址。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEINVAL:尚未使用Bind绑定套接字。WSAENOTCONN:套接字未连接(仅限SOCK_STREAM)。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将ReceiveFrom设置为 0 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,ReceiveFrom操作会进行阻止。WSAEMSGSIZE:数据报太大,无法放入指定的缓冲区,因此被截断。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。
备注
此函数用于读取(可能已连接的)套接字上的传入数据,并捕获从其发送数据的地址。
若要处理 IPv6 地址,请使用 CAsyncSocket::ReceiveFromEx。
对于类型为 SOCK_STREAM 的套接字,将会返回当前可用的信息,最高信息量为提供的缓冲区的大小。 如果已将套接字配置为以内联方式接收带外数据(套接字选项 SO_OOBINLINE)且带外数据为未读,则仅返回带外数据。 应用程序可以使用 IOCtlSIOCATMARK 选项或 OnOutOfBandData 来确定是否要读取更多带外数据。 为 lpSockAddr 套接字忽略 lpSockAddrLen 和 SOCK_STREAM 参数。
对于数据报套接字,数据将从第一个排队的数据报中提取,最大大小为提供的缓冲区大小。 如果数据报大于提供的缓冲区,则会为缓冲区填充消息的第一部分,多余的数据会丢失。ReceiveFrom 会返回值 SOCKET_ERROR,错误代码设置为 WSAEMSGSIZE。
如果 lpSockAddr 为非零值,并且套接字的类型为 SOCK_DGRAM,则发送了数据的套接字的网络地址将复制到相应的 SOCKADDR 结构。
lpSockAddrLen 所指向的值将初始化为此结构的大小,并在返回时进行修改以指示存储在那里的地址的实际大小。 如果套接字上没有可用的传入数据,则 ReceiveFrom 调用会等待数据到达,除非套接字是非阻止型。 在这种情况下,会返回值 SOCKET_ERROR,错误代码设置为 WSAEWOULDBLOCK。
OnReceive 回调可用于确定何时会有更多数据到达。
如果套接字的类型为 SOCK_STREAM,且远端已正常关闭连接,则 ReceiveFrom 会立即完成,接收的字节数为 0。
CAsyncSocket::ReceiveFromEx
调用此成员函数可接收数据报并将源地址存储在 SOCKADDR 结构或 rSocketAddress 中(处理 IPv6 地址)。
int ReceiveFromEx(
void* lpBuf,
int nBufLen,
CString& rSocketAddress,
UINT& rSocketPort,
int nFlags = 0);
参数
lpBuf
传入数据的缓冲区。
nBufLen
lpBuf 的长度(以字节为单位)。
rSocketAddress
对接收以点分隔的数字 IP 地址的 CString 对象的引用。
rSocketPort
对存储端口的 UINT 的引用。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_PEEK:速览传入数据。 数据会复制到缓冲区中,但不会从输入队列中删除。MSG_OOB:处理带外数据。
返回值
如果未发生错误,ReceiveFromEx 会返回收到的字节数。 如果连接已关闭,则会返回 0。 否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULT:lpSockAddrLen参数无效:lpSockAddr缓冲区太小,无法容纳对等机地址。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEINVAL:尚未使用Bind绑定套接字。WSAENOTCONN:套接字未连接(仅限SOCK_STREAM)。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将ReceiveFromEx设置为 0 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,ReceiveFromEx操作会进行阻止。WSAEMSGSIZE:数据报太大,无法放入指定的缓冲区,因此被截断。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。
备注
此函数用于读取(可能已连接的)套接字上的传入数据,并捕获从其发送数据的地址。
此函数与 CAsyncSocket::ReceiveFrom 相同,只是它处理 IPv6 地址和较旧的协议。
对于类型为 SOCK_STREAM 的套接字,将会返回当前可用的信息,最高信息量为提供的缓冲区的大小。 如果已将套接字配置为以内联方式接收带外数据(套接字选项 SO_OOBINLINE)且带外数据为未读,则仅返回带外数据。 应用程序可以使用 IOCtlSIOCATMARK 选项或 OnOutOfBandData 来确定是否要读取更多带外数据。 为 lpSockAddr 套接字忽略 lpSockAddrLen 和 SOCK_STREAM 参数。
对于数据报套接字,数据将从第一个排队的数据报中提取,最大大小为提供的缓冲区大小。 如果数据报大于提供的缓冲区,则会为缓冲区填充消息的第一部分,多余的数据会丢失。ReceiveFromEx 会返回值 SOCKET_ERROR,错误代码设置为 WSAEMSGSIZE。
如果 lpSockAddr 为非零值,并且套接字的类型为 SOCK_DGRAM,则发送了数据的套接字的网络地址将复制到相应的 SOCKADDR 结构。
lpSockAddrLen 所指向的值将初始化为此结构的大小,并在返回时进行修改以指示存储在那里的地址的实际大小。 如果套接字上没有可用的传入数据,则 ReceiveFromEx 调用会等待数据到达,除非套接字是非阻止型。 在这种情况下,会返回值 SOCKET_ERROR,错误代码设置为 WSAEWOULDBLOCK。
OnReceive 回调可用于确定何时会有更多数据到达。
如果套接字的类型为 SOCK_STREAM,且远端已正常关闭连接,则 ReceiveFromEx 会立即完成,接收的字节数为 0。
CAsyncSocket::Send
调用此成员函数可在连接的套接字上发送数据。
virtual int Send(
const void* lpBuf,
int nBufLen,
int nFlags = 0);
参数
lpBuf
一个包含要传输的数据的缓冲区。
nBufLen
lpBuf 中数据的长度(以字节为单位)。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_DONTROUTE:指定数据不应受到路由的约束。 Windows 套接字供应商可以选择忽略此标志。MSG_OOB:发送带外数据(仅限SOCK_STREAM)。
返回值
如果未发生错误,Send 会返回发送的字符总数。 (请注意,这可能小于 nBufLen 指示的数字。)否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEACCES:请求的地址是广播地址,但相应的标志未设置。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEFAULT:lpBuf参数不在用户地址空间的有效部分。WSAENETRESET:必须重置连接,因为 Windows 套接字实现删除了连接。WSAENOBUFS:Windows 套接字实现报告缓冲区死锁。WSAENOTCONN:套接字未连接。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将Send设置为 1 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,请求的操作会进行阻止。WSAEMSGSIZE:套接字的类型为SOCK_DGRAM,数据报大于 Windows 套接字实现支持的最大大小。WSAEINVAL:尚未使用Bind绑定套接字。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。
备注
Send 用于在连接的流或数据报套接字上写入传出数据。 对于数据报套接字,必须注意不要超过基础子网的最大 IP 数据包大小,该大小由 iMaxUdpDg 所返回的 WSADATA 结构中的 AfxSocketInit 元素提供。 如果数据太长,无法通过基础协议以原子方式传递,则会通过 WSAEMSGSIZE 返回错误 GetLastError,不会传输任何数据。
请注意,对于数据报套接字,成功完成 Send 并不表示数据已成功传递。
在类型为 CAsyncSocket 的 SOCK_STREAM 对象上,写入的字节数可以在 1 到请求的长度的范围内,具体取决于本地主机和外部主机上的缓冲区可用性。
示例
请参阅 CAsyncSocket::OnSend 的示例。
CAsyncSocket::SendTo
调用此成员函数可将数据发送到特定目标。
int SendTo(
const void* lpBuf,
int nBufLen,
UINT nHostPort,
LPCTSTR lpszHostAddress = NULL,
int nFlags = 0);
int SendTo(
const void* lpBuf,
int nBufLen,
const SOCKADDR* lpSockAddr,
int nSockAddrLen,
int nFlags = 0);
参数
lpBuf
一个包含要传输的数据的缓冲区。
nBufLen
lpBuf 中数据的长度(以字节为单位)。
nHostPort
标识套接字应用程序的端口。
lpszHostAddress
此对象连接到的套接字的网络地址:计算机名称(如“ftp.microsoft.com”)或以点分隔的数字(如“128.56.22.8”)。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_DONTROUTE:指定数据不应受到路由的约束。 Windows 套接字供应商可以选择忽略此标志。MSG_OOB:发送带外数据(仅限SOCK_STREAM)。
lpSockAddr
一个指向 SOCKADDR 结构的指针,该结构包含目标套接字的地址。
nSockAddrLen
lpSockAddr 中的地址的长度(以字节为单位)。
返回值
如果未发生错误,SendTo 会返回发送的字符总数。 (请注意,这可能小于 nBufLen 指示的数字。)否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEACCES:请求的地址是广播地址,但相应的标志未设置。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEFAULT:lpBuf或lpSockAddr参数不是用户地址空间的一部分,或者lpSockAddr参数太小(小于SOCKADDR结构的大小)。WSAEINVAL:主机名无效。WSAENETRESET:必须重置连接,因为 Windows 套接字实现删除了连接。WSAENOBUFS:Windows 套接字实现报告缓冲区死锁。WSAENOTCONN:套接字未连接(仅限SOCK_STREAM)。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将SendTo设置为 1 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,请求的操作会进行阻止。WSAEMSGSIZE:套接字的类型为SOCK_DGRAM,数据报大于 Windows 套接字实现支持的最大大小。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。WSAEADDRNOTAVAIL:指定的地址不能从本地计算机使用。WSAEAFNOSUPPORT:指定的系列中的地址无法与此套接字配合使用。WSAEDESTADDRREQ:需要目标地址。WSAENETUNREACH:此时不可从此主机访问该网络。
备注
SendTo 用在数据报或流套接字上,用于在套接字上写入传出数据。 对于数据报套接字,必须注意不要超过基础子网的最大 IP 数据包大小,该大小由 iMaxUdpDg 所填充的 WSADATA 结构中的 AfxSocketInit 元素提供。 如果数据太长,无法通过基础协议以原子方式传递,则会返回错误 WSAEMSGSIZE,不会传输任何数据。
请注意,成功完成 SendTo 并不表示数据已成功传递。
SendTo 仅在 SOCK_DGRAM 套接字上使用,可将数据报发送到由 lpSockAddr 参数标识的特定套接字。
若要发送广播(仅在 SOCK_DGRAM 上),应使用特殊 IP 地址 lpSockAddr(在 Windows 套接字头文件 INADDR_BROADCAST 中定义)和所需端口号来构造 WINSOCK.H 参数中的地址。 或者,如果 lpszHostAddress 参数为 NULL,则为广播配置套接字。 广播数据报通常不应超过出现的碎片的大小,这意味着数据报的数据部分(不包括标头)不应超过 512 字节。
若要处理 IPv6 地址,请使用 CAsyncSocket::SendToEx。
CAsyncSocket::SendToEx
调用此成员函数可将数据发送到特定目标(处理 IPv6 地址)。
int SendToEx(
const void* lpBuf,
int nBufLen,
UINT nHostPort,
LPCTSTR lpszHostAddress = NULL,
int nFlags = 0);
参数
lpBuf
一个包含要传输的数据的缓冲区。
nBufLen
lpBuf 中数据的长度(以字节为单位)。
nHostPort
标识套接字应用程序的端口。
lpszHostAddress
此对象连接到的套接字的网络地址:计算机名称(如“ftp.microsoft.com”)或以点分隔的数字(如“128.56.22.8”)。
nFlags
指定进行调用的方式。 此函数的语义取决于套接字选项和 nFlags 参数。 后者是通过将以下任何值与 C++ 按位或运算符 (|) 组合使用来构造的:
MSG_DONTROUTE:指定数据不应受到路由的约束。 Windows 套接字供应商可以选择忽略此标志。MSG_OOB:发送带外数据(仅限SOCK_STREAM)。
返回值
如果未发生错误,SendToEx 会返回发送的字符总数。 (请注意,这可能小于 nBufLen 指示的数字。)否则会返回值 SOCKET_ERROR。可以通过调用 GetLastError 来检索特定错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEACCES:请求的地址是广播地址,但相应的标志未设置。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEFAULT:lpBuf或lpSockAddr参数不是用户地址空间的一部分,或者lpSockAddr参数太小(小于SOCKADDR结构的大小)。WSAEINVAL:主机名无效。WSAENETRESET:必须重置连接,因为 Windows 套接字实现删除了连接。WSAENOBUFS:Windows 套接字实现报告缓冲区死锁。WSAENOTCONN:套接字未连接(仅限SOCK_STREAM)。WSAENOTSOCK:描述符不是套接字。WSAEOPNOTSUPPMSG_OOB指定了套接字,但套接字的类型不是SOCK_STREAM。WSAESHUTDOWN:套接字已关闭;在将SendToEx设置为 1 或 2 的情况下调用ShutDown后,无法在套接字上调用nHow。WSAEWOULDBLOCK:套接字标记为非阻止,请求的操作会进行阻止。WSAEMSGSIZE:套接字的类型为SOCK_DGRAM,数据报大于 Windows 套接字实现支持的最大大小。WSAECONNABORTED:由于超时或其他故障,虚拟线路已中止。WSAECONNRESET:虚拟线路已由远端重置。WSAEADDRNOTAVAIL:指定的地址不能从本地计算机使用。WSAEAFNOSUPPORT:指定的系列中的地址无法与此套接字配合使用。WSAEDESTADDRREQ:需要目标地址。WSAENETUNREACH:此时不可从此主机访问该网络。
备注
此方法与 CAsyncSocket::SendTo 相同,只是它处理 IPv6 地址和较旧的协议。
SendToEx 用在数据报或流套接字上,用于在套接字上写入传出数据。 对于数据报套接字,必须注意不要超过基础子网的最大 IP 数据包大小,该大小由 iMaxUdpDg 所填充的 WSADATA 结构中的 AfxSocketInit 元素提供。 如果数据太长,无法通过基础协议以原子方式传递,则会返回错误 WSAEMSGSIZE,不会传输任何数据。
请注意,成功完成 SendToEx 并不表示数据已成功传递。
SendToEx 仅在 SOCK_DGRAM 套接字上使用,可将数据报发送到由 lpSockAddr 参数标识的特定套接字。
若要发送广播(仅在 SOCK_DGRAM 上),应使用特殊 IP 地址 lpSockAddr(在 Windows 套接字头文件 INADDR_BROADCAST 中定义)和所需端口号来构造 WINSOCK.H 参数中的地址。 或者,如果 lpszHostAddress 参数为 NULL,则为广播配置套接字。 广播数据报通常不应超过出现的碎片的大小,这意味着数据报的数据部分(不包括标头)不应超过 512 字节。
CAsyncSocket::SetSockOpt
调用此成员函数可设置套接字选项。
BOOL SetSockOpt(
int nOptionName,
const void* lpOptionValue,
int nOptionLen,
int nLevel = SOL_SOCKET);
参数
nOptionName
要为其设置值的套接字选项。
lpOptionValue
一个指向缓冲区的指针,在该缓冲区中提供所请求的选项的值。
nOptionLen
lpOptionValue 缓冲区的大小(以字节为单位)。
nLevel
定义选项时所在的级别;唯一受支持的级别是 SOL_SOCKET 和 IPPROTO_TCP。
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEFAULTlpOptionValue不在进程地址空间的有效部分。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAEINVALnLevel无效,或者信息无效lpOptionValue。WSAENETRESET:设置SO_KEEPALIVE时,连接已超时。WSAENOPROTOOPT:选项未知或不受支持。 具体而言,SO_BROADCAST在类型为SOCK_STREAM的套接字上不受支持,而SO_DONTLINGER、SO_KEEPALIVE、SO_LINGER和SO_OOBINLINE在类型为SOCK_DGRAM的套接字上不受支持。WSAENOTCONN:设置SO_KEEPALIVE时已重置连接。WSAENOTSOCK:描述符不是套接字。
备注
SetSockOpt 设置与任何类型、任何状态的套接字关联的套接字选项的当前值。 尽管选项可以存在于多个协议级别,但此规范仅定义位于最上层“套接字”级别的选项。 选项会影响套接字操作,例如是否在正常数据流中接收加急数据、是否可以在套接字上发送广播消息,等等。
有两种类型的套接字选项:启用或禁用功能或行为的布尔选项,以及需要整数值或结构的选项。 若要启用布尔选项,请让 lpOptionValue 指向非零整数。 若要禁用该选项,请让 lpOptionValue 指向等于零的整数。 对于布尔选项,nOptionLen 应等于 sizeof(BOOL)。 对于其他选项,lpOptionValue 指向包含选项所需值的整数或结构,nOptionLen 是整数或结构的长度。
SO_LINGER 控制在套接字上将未发送的数据排队时执行的操作。调用 Close 函数可关闭套接字。
默认情况下,套接字无法绑定(参见 Bind)到已被使用的本地地址。 但是,有时可能需要以这种方式“重用”地址。 由于每个连接都是通过本地地址和远程地址的组合唯一标识的,因此只要远程地址不同,将两个套接字绑定到同一个本地地址就没有问题。
若要通知 Windows 套接字实现不应禁止对套接字进行的 Bind 调用(因为所需的地址已由另一个套接字使用),应用程序应在发出 SO_REUSEADDR 调用之前为套接字设置 Bind 套接字选项。 请注意,仅在进行 Bind 调用时才解释该选项,因此不需要在未绑定到现有地址的套接字上设置该选项(虽然这样做无害);在进行 Bind 调用后设置或重置该选项不会影响此套接字或任何其他套接字。
应用程序可以通过启用 SO_KEEPALIVE 套接字选项,请求 Windows 套接字实现允许在传输控制协议 (TCP) 连接上使用“保持连接”数据包。 Windows 套接字实现不需要支持使用“保持连接”:如果这样做,则精确语义是特定于实现的,但应符合 RFC 1122“Internet 主机要求 — 通信层”的 4.2.3.6 部分的要求。如果由于“保持连接”而断开了某个连接,则会将错误代码 WSAENETRESET 返回到套接字上正在进行的任何调用,任何后续调用都将失败并出现 WSAENOTCONN 错误。
TCP_NODELAY 选项禁用 Nagle 算法。 Nagle 算法用于通过缓冲未确认的发送数据来减少主机发送的小数据包数,直到可以发送完全大小的数据包。 但是,对于某些应用程序,此算法可能会妨碍性能,因此可使用 TCP_NODELAY 将其关闭。 应用程序编写器不应设置 TCP_NODELAY,除非你十分了解这样做的影响,并且该影响正是你所需要的,因为设置 TCP_NODELAY 可能会对网络性能产生重大负面影响。
TCP_NODELAY 是唯一受支持的使用级别 IPPROTO_TCP 的套接字选项;所有其他选项都使用级别 SOL_SOCKET。
如果应用程序设置了 SO_DEBUG 选项,则 Windows 套接字的某些实现提供输出调试信息。
SetSockOpt 支持以下选项。 “类型”标识 lpOptionValue 所寻址的数据的类型。
| 值 | 类型 | 含义 |
|---|---|---|
SO_BROADCAST |
BOOL |
允许在套接字上传输广播消息。 |
SO_DEBUG |
BOOL |
记录调试信息。 |
SO_DONTLINGER |
BOOL |
不要阻止正在等待未发送数据发送的 Close。 设置此选项等效于在将 SO_LINGER 设置为零的情况下设置 l_onoff。 |
SO_DONTROUTE |
BOOL |
不要进行路由:直接发送到接口。 |
SO_KEEPALIVE |
BOOL |
发送“保持连接”。 |
SO_LINGER |
struct LINGER |
如果存在未发送的数据,则在执行 Close 时逗留。 |
SO_OOBINLINE |
BOOL |
接收正常数据流中的带外数据。 |
SO_RCVBUF |
int |
指定接收操作的缓冲区大小。 |
SO_REUSEADDR |
BOOL |
允许将套接字绑定到已在使用中的地址。 (请参阅绑定。) |
SO_SNDBUF |
int |
指定发送操作的缓冲区大小。 |
TCP_NODELAY |
BOOL |
为发送合并禁用 Nagle 算法。 |
SetSockOpt 不支持的伯克利软件发行版 (BSD) 选项如下:
| 值 | 类型 | 含义 |
|---|---|---|
SO_ACCEPTCONN |
BOOL |
套接字正在侦听 |
SO_ERROR |
int |
获取错误状态并进行清除。 |
SO_RCVLOWAT |
int |
接收低水印。 |
SO_RCVTIMEO |
int |
接收超时 |
SO_SNDLOWAT |
int |
发送低水印。 |
SO_SNDTIMEO |
int |
发送超时。 |
SO_TYPE |
int |
套接字的类型。 |
IP_OPTIONS |
在 IP 标头中设置选项字段。 |
CAsyncSocket::ShutDown
调用此成员函数可禁用在套接字上进行的发送和/或接收操作。
BOOL ShutDown(int nHow = sends);
参数
nHow
一个标志,它使用以下枚举值描述不再允许哪些类型的操作:
接收 = 0
发送 = 1
两者 = 2
返回值
如果函数成功,则为非零值;否则为 0,并且可以通过调用 GetLastError 来检索特定的错误代码。 以下错误适用于此成员函数:
WSANOTINITIALISED:在使用此 API 之前,AfxSocketInit必须成功。WSAENETDOWN:Windows 套接字实现检测到网络子系统失败。WSAEINVALnHow无效。WSAEINPROGRESS:正在执行阻止型 Windows 套接字操作。WSAENOTCONN:套接字未连接(仅限SOCK_STREAM)。WSAENOTSOCK:描述符不是套接字。
备注
ShutDown 用在所有类型的套接字上,可禁用接收和/或传输。 如果 nHow 为 0,则不允许在套接字上进行后续接收。 这不会影响较低的协议层。
对于传输控制协议 (TCP),TCP 窗口不会更改,传入数据会被接受(但不会被确认),直到窗口耗尽。 对于用户数据报协议 (UDP),传入数据报会被接受并排队。 在任何情况下都不会生成 ICMP 错误数据包。 如果 nHow 为 1,则不允许后续发送。 对于 TCP 套接字,将发送 FIN。 将 nHow 设置为 2 会禁用发送和接收,如上所述。
请注意,ShutDown 不会关闭套接字,在调用 Close 之前不会释放附加到套接字的资源。 应用程序不应依赖于在关闭套接字后能够重用套接字的功能。 具体说来,Windows 套接字实现不需支持在此类套接字上使用 Connect 的功能。
示例
请参阅 CAsyncSocket::OnReceive 的示例。
CASyncSocket::Socket
分配套接字句柄。
BOOL Socket(
int nSocketType = SOCK_STREAM,
long lEvent = FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE,
int nProtocolType = 0,
int nAddressFormat = PF_INET);
参数
nSocketType
指定 SOCK_STREAM 或 SOCK_DGRAM。
lEvent
位掩码,指定应用程序感兴趣的网络事件的组合。
FD_READ:想要接收准备读取的通知。FD_WRITE:想要接收准备写入的通知。FD_OOB:想要接收带外数据的到达通知。FD_ACCEPT:想要接收传入连接的通知。FD_CONNECT:想要接收已完成连接的通知。FD_CLOSE:想要接收套接字关闭的通知。
nProtocolType
要与特定于所指示的地址系列的套接字配合使用的协议。
nAddressFormat
地址系列规范。
返回值
成功时返回 TRUE,失败时返回 FALSE。
备注
此方法分配套接字句柄。 它不调用 CAsyncSocket::Bind 来将套接字绑定到指定地址,因此你需要稍后调用 Bind 以将套接字绑定到指定地址。 在绑定套接字选项之前,可以使用 CAsyncSocket::SetSockOpt 来设置套接字选项。