WSAGetLastError() 返回的错误(转载)

原文地址:未能找最初的地址,只有转载地址,也附上:http://yaningchen.blog.sohu.com/159708949.html

 

 

WSAGetLastError() 返回的错误(转载)

 

下面列示了用户在 Windows 操作系统上使用 TCP/IP 时,可能最常遇到的错误代码。它不是完整的错误列表。可以在文件 winsock2.h 中找到 WSAGetLastError() 返回的错误。如果您未安装开发环境,则在您的系统上可能未安装此文件。在“Windows 套接字 2 应用程序编程接口”中说明了关于特定函数返回的错误的更多信息。可以从下列 Web 站点获取此规范的副本:http://www.sockets.com/winsock2.htm#Docs

    * WSAEINVAL (10022):无效自变量。它也可以表示套接字的当前状态与要调用的 TCP 函数不兼容,或套接字可能不再有效。
    * WSAEMFILE (10024):打开的文件太多。打开的套接字太多。每个实现可以有一个全局、每进程或每线程可用的套接字句柄的最大数目。
    * WSAEWOULDBLOCK (10035):资源暂时不可用。从在非分块的套接字上不能立即完成的操作返回此错误。
    * WSAEINPROGRESS (10036):正在进行分块“Windows 套接字”操作。“Windows 套接字”仅允许每个任务(或线程)有单个分块操作未完成,并且如果进行任何其它函数调用,则函数由于 WSAEINPROGRESS 而失败。
    * WSAENOPROTOOPT (10042):错误协议选项。在 getsockopt() 或 setsockopt() 调用中指定了未知、无效或不受支持的选项或级别。
    * WSAEADDRINUSE (10048):地址已经在使用。通常仅允许每个套接字地址(协议/IP 地址/端口)的一种使用。如果应用程序试图将套接字 bind() 至 IP 地址/端口,而该 IP 地址/端口已经用于现有套接字、未正确关闭的套接字或仍处于关闭进程中的套接字,则发生此错误。
    * WSAENETDOWN (10050):网络已停止。套接字操作遇到了失效网络。这可能指示网络系统(即,WinSock DLL 溢出的协议堆栈)、网络接口或本地网络本身的严重故障。
    * WSAENETUNREACH (10051):网络不可到达。试图对不可到达的网络执行套接字操作。这通常表示本地软件知道没有到达远程主机的路由。
    * WSAENETRESET (10052):网络复位时删除了连接。由于该操作正在进行时“保持活动”活动检测到故障,已中断连接。如果试图在已经失败的连接中设置 SO_KEEPALIVE,则也可能是由 stsockopt() 返回的。
    * WSAECONNABORTED (10053):软件导致了连接异常终止。可能由于数据传送超时或协议错误,机器上的软件异常终止了已建立的连接,
    * WSAECONNRESET (10054):连接由对等设备复位。远程对等设备强制关闭了现有连接。如果远程机器上的对等应用程序突然停止,机器重新引导,或对等应用程序在远程套接字中使用了“硬关闭”,则通常会导致此结果。如果由于一个或多个操作正在进行时“保持活动”活动检测到故障而中断连接,则也可能导致此错误。正在进行的操作由于 WSAENETRESET 而失败。后续操作由于 WSAECONNRESET 而失败。
    * WSAENOBUFS (10055):没有可用缓冲区空间。因为系统缺乏足够缓冲区空间或由于队列已满,所以可能无法执行套接字上的操作。
    * WSAENOTCONN (10057):未连接套接字。
    * WSAETIMEDOUT (10060):连接超时。因为在一段时间后连接的一方未正确响应,所以连接尝试失败。
    * WSAECONNREFUSED (10061):连接已被拒绝。如果正在尝试连接至实例或连接至数据库,则检查是否已成功启动服务器上的数据库管理器和 TCP/IP 协议支持。
    * WSAEHOSTUNREACH (10065):没有至主机的路由。试图对不可到达的机器执行套接字操作。
    * WSASYSNOTREADY (10091):基础网络子系统未准备好进行网络通信。用户应该检查相应的“Windows 套接字 DLL”是否位于当前路径中,并检查它们是否未尝试同时使用多个 WinSock 实现。如果在您的系统上存在多个 WinSock DLL,则确保路径中的第一个 WinSock DLL 适合于当前已装入的网络子系统,并确保当前已安装并已正确配置所有必要的组件。
    * WSAVERNOTSUPPORTED (10092):此特定的“Windows 套接字”实现未提供请求的“Windows 套接字 API”支持的版本。检查是否未访问旧的“Windows 套接字 DLL”文件。
    * WSA_E_NO_MORE (10110), WSAENOMORE (10102):没有可用数据。在“Windows 套接字”版本 2 中,为 WSAENOMORE 和 WSA_E_NO_MORE 定义了冲突的错误代码。在以后版本中将除去错误代码 WSAENOMORE,只有 WSA_E_NO_MORE 将保留。
    * WSAHOST_NOT_FOUND (11001):找不到主机。
    * WSATRY_AGAIN (11002):找不到主机。因为本地机器未接收到来自名称服务器的响应,所以请求从名称服务器中检索主机名的 IP 地址失败。
    * WSANO_DATA (11004):名称无效,没有请求的类型的数据记录。名称服务器或 hosts 文件不识别主机名,或者在 services 文件中未指定服务名。

 

<think>好的,用户现在遇到了WSAgetlasterror返回10038的问题,需要我来帮忙解决。首先,我需要回忆一下这个错误码对应的具体含义。根据之前的资料,错误码10038对应的是WSAENOTSOCK,也就是“在一个非套接字上尝试了一个操作”。这说明用户可能在调用某个套接字相关的函数时,传入了一个无效的套接字描述符。 接下来,我要考虑用户为什么会遇到这个问题。可能的情况包括:套接字未被正确初始化就已经被使用,或者在套接字关闭后再次调用相关函数,或者传递了错误的句柄,甚至可能是在多线程环境中套接字被意外关闭。此外,用户可能在使用Qt时混合了不同库的套接字接口,例如同时使用Qt的套接字类和原生的WinSock API,导致管理混乱。 我需要一步步引导用户检查他们的代码。首先,检查所有使用套接字的地方,确保socket()调用成功返回了有效的套接字描述符。如果socket创建失败,后续的操作自然会出错。然后,确认在调用sendto、recvfrom等函数时,传入的套接字参数是正确的,没有被意外关闭或覆盖。另外,用户可能在关闭套接字后没有正确清理,导致后续误用已经关闭的套接字。需要提醒他们在关闭套接字后,将对应的变量设为INVALID_SOCKET,避免重复使用。 另外,多线程环境下如果多个线程操作同一个套接字而没有适当的同步机制,可能导致竞争条件,例如一个线程关闭了套接字,而另一个线程还在使用它。这时候需要检查线程同步机制,确保套接字操作的安全性。 还有可能用户错误地使用了其他类型的句柄(如文件句柄)当作套接字传递,这显然会导致错误。需要检查代码中所有涉及套接字的地方,确认传递的是正确的类型。 最后,建议用户使用调试工具逐步跟踪代码,检查套接字变量的值,尤其是在调用可能出错的函数前后,确认套接字状态的变化。同时,使用日志输出套接字的值和错误发生的位置,有助于快速定位问题所在。 总结下来,我需要用清晰的结构,分点列出可能的原因和对应的解决方法,帮助用户系统地排查问题。同时,提醒他们在编程时注意套接字生命周期的管理和线程安全,避免类似错误的再次发生。</think>在Windows网络编程中,`WSAgetlasterror` 返回错误代码 **10038** 对应 `WSAENOTSOCK`,表示**对非套接字对象执行了套接字操作**。以下是详细分析和解决方案: --- ### **1. 错误原因** 错误码 **10038** 的典型场景: - 套接字未正确初始化(例如未调用 `socket()` 或调用失败)。 - 套接字已关闭(`closesocket()` 后继续使用)。 - 传入的句柄是文件句柄或其他非套接字类型。 - 多线程环境中套接字被意外覆盖或释放。 - 混用 Qt 网络库和原生 WinSock 接口导致句柄冲突。 --- ### **2. 排查步骤** #### **(1) 检查套接字创建** 确认 `socket()` 调用成功且返回值有效: ```cpp SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s == INVALID_SOCKET) { int error = WSAGetLastError(); qDebug() << "Socket creation failed. Error code:" << error; return; } ``` #### **(2) 验证套接字使用范围** 确保在调用 `sendto()`、`recvfrom()` 等函数时,套接字 `s` 仍有效: ```cpp // 错误示例:套接字已关闭后调用 closesocket(s); sendto(s, ...); // 触发 10038 ``` #### **(3) 检查多线程竞争** 若多线程操作同一套接字,需通过锁(如 `QMutex`)保证原子性: ```cpp QMutexLocker locker(&socketMutex); // 加锁 if (s != INVALID_SOCKET) { sendto(s, ...); } ``` #### **(4) 避免句柄混淆** 禁止将 Qt 的 `QTcpSocket` 或 `QUdpSocket` 的句柄与 WinSock 混用: ```cpp // 错误示例:混合 Qt 和 WinSock QTcpSocket qtSocket; SOCKET s = qtSocket.socketDescriptor(); // 可能不可靠 sendto(s, ...); // 潜在风险 ``` --- ### **3. 解决方案** #### **(1) 确保套接字生命周期** - 仅在必要时创建套接字,使用完毕后立即关闭: ```cpp SOCKET s = socket(...); if (s != INVALID_SOCKET) { // 使用套接字 closesocket(s); s = INVALID_SOCKET; // 显式标记为无效 } ``` #### **(2) 添加防御性编程** 在每次操作前检查套接字有效性: ```cpp if (s == INVALID_SOCKET) { qDebug() << "Socket is invalid!"; return; } int result = sendto(s, ...); ``` #### **(3) 使用调试工具** - **日志输出**:记录套接字创建、使用和关闭的日志。 - **Wireshark**:抓包验证是否实际发送了数据。 - **调试器**:检查套接字变量的值是否为 `INVALID_SOCKET`(通常为 `-1`)。 --- ### **4. 常见错误场景示例** #### **场景1:未初始化套接字** ```cpp SOCKET s = INVALID_SOCKET; // 未调用 socket() sendto(s, ...); // 触发 10038 ``` #### **场景2:重复关闭套接字** ```cpp closesocket(s); closesocket(s); // 第二次关闭已无效的套接字,可能破坏其他资源 ``` --- ### **5. 总结** 错误 10038 的核心是**操作了一个无效的套接字句柄**。通过以下措施可避免: 1. 严格管理套接字生命周期。 2. 操作前检查套接字有效性。 3. 避免多线程竞争和资源泄漏。 4. 优先使用单一网络库(纯 WinSock 或 Qt 网络模块)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值