65.9K
CodeProject 正在变化。 阅读更多。
Home

XWSAError - 用于 Winsock 错误查找的 DLL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.89/5 (18投票s)

2005年1月6日

CPOL

4分钟阅读

viewsIcon

54855

downloadIcon

629

使用此 DLL 将 Winsock 错误查找功能添加到您的 C++ 或 VB 应用程序中。

引言

最近,我一直在使用 Winsock 处理我第N个客户端/服务器应用程序,我又一次发现自己将 Winsock 错误描述嵌入到应用程序中。由于没有像往常一样的压力(意思是:我还没错过截止日期),我决定将 Winsock 错误描述集中到一个方便的 DLL 中。

我在 MSDN 上找到了一张表格,作为 Winsock 错误的权威来源:Windows Sockets 错误代码

这是该表的前几项:

返回代码/值 描述
WSAEINTR
10004
中断的函数调用.
一个阻塞操作被对 WSACancelBlockingCall 的调用中断。
WSAEACCES
10013
拒绝访问.
尝试以禁止的方式访问套接字。例如,在没有使用 setsockopt(SO_BROADCAST) 设置广播权限的情况下,对 sendto 使用广播地址。

WSAEACCES 错误的另一个可能原因是,当调用 bind 函数时(在 Windows NT 4 SP4 或更高版本上),另一个应用程序、服务或内核模式驱动程序已独占访问绑定到同一地址。这种独占访问是 Windows NT 4 SP4 及更高版本的一项新功能,通过使用 SO_EXCLUSIVEADDRUSE 选项实现。

WSAEFAULT
10014
无效地址.
系统在尝试使用指针参数进行调用时检测到无效的指针地址。如果应用程序传递了无效的指针值,或者缓冲区的长度太小,就会出现此错误。例如,如果一个参数(一个 sockaddr 结构)的长度小于 sizeof(sockaddr)

查看此表,很明显每个错误代码都有四个感兴趣的项目:

  1. 错误代码 - 例如,WSAEFAULT
  2. 错误代码的数值 - 例如,10014
  3. 简短描述 - 例如,无效地址。
  4. 详细描述 - 一个长度在 50 到 800 个字符之间的文本字符串。
注意:Winsock 错误代码在 winsock2.h 中定义。

XWSAError 函数

XWSAError.dll 包含检索错误代码字符串(给定错误代码)、数值错误代码(给定错误代码字符串)、简短描述和详细描述的函数。还包括获取返回字符串最大长度的函数(如果您要检索详细描述,可能更简单的方法是为详细描述字符串分配一个缓冲区,并为其他字符串也使用该缓冲区)。

以下是 XWSAError.dll 中可用的函数:

  • XWSA_GetErrorCode() - 从错误代码字符串检索错误代码。
    /////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorCode()
    //
    // Purpose:     Retrieve numeric error code associated with error code string.
    //              For example, calling XWSA_GetErrorCode() with an error code
    //              string of "WSAEINTR" will return the value 10004.
    //
    // Parameters:  lpszErrorString - [in] pointer to error code string
    //
    // Returns:     int - numeric value of error code
    //
  • XWSA_GetErrorString() - 从错误代码检索错误代码字符串。
    ////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorString()
    //
    // Purpose:     Retrieve the string associated with the error code. For
    //              example, calling XWSA_GetErrorString() with an error code
    //              of 10004 will return the string "WSAEINTR".
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code string found; 0 otherwise
    //
  • XWSA_GetLongDescription() - 检索详细描述。
    /////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetLongDescription()
    //
    // Purpose:     Retrieve the long description string associated with the
    //              error code.
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code found; 0 otherwise
    //
  • XWSA_GetShortDescription() - 检索简短描述。
    ////////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetShortDescription()
    //
    // Purpose:     Retrieve the short description string associated with the
    //              error code.
    //
    // Parameters:  nErrorCode - [in] Winsock error code
    //              lpszBuf    - [out] pointer to buffer that receives the string
    //              nBufSize   - [in] size of buffer in TCHARs
    //
    // Returns:     int - 1 if error code found; 0 otherwise
    //
  • XWSA_GetErrorStringSize() - 检索错误代码字符串的最大大小。
    //////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetErrorStringSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of an error code string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of an error code string
    //
  • XWSA_GetLongDescriptionSize() - 检索详细描述的最大大小。
    /////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetLongDescriptionSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of a long description
    //              string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of a long description string
    //
  • XWSA_GetShortDescriptionSize() - 检索简短描述的最大大小。
    //////////////////////////////////////////////////////////////////////////
    //
    // XWSA_GetShortDescriptionSize()
    //
    // Purpose:     Returns the maximum size in TCHARs of a short description
    //              string.
    //
    // Parameters:  none
    //
    // Returns:     int - maximum size in TCHARs of a short description string
    //

示例代码

以下示例代码 - 取自演示应用程序 - 显示了如何使用上述函数。

    // is this a numeric error code (10004) or an error string ("WSAEINTR")
    if (bNumeric)
    {
        int nCode = _ttoi(m_strError);

        m_Code.SetWindowText(m_strError);

        if (XWSA_GetErrorString(nCode, buf, XWSA_GetLongDescriptionSize()))
        {
            m_ID.SetWindowText(buf);
            if (XWSA_GetShortDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
                m_ShortDescription.SetWindowText(buf);
            if (XWSA_GetLongDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
                m_LongDescription.SetWindowText(buf);
        }
        else
        {
            m_ID.SetWindowText(_T("unknown error code"));
        }
    }
    else
    {
        int nCode = XWSA_GetErrorCode(m_strError);

        if (nCode)
        {
            m_ID.SetWindowText(m_strError);

            CString s = _T("");
            s.Format(_T("%d"), nCode);

            m_Code.SetWindowText(s);

            if (XWSA_GetShortDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
                m_ShortDescription.SetWindowText(buf);
            if (XWSA_GetLongDescription(nCode, buf, XWSA_GetLongDescriptionSize()))
                m_LongDescription.SetWindowText(buf);
        }
    }

如何在 Visual C++ 中使用

要将 XWSAError.dll 集成到您的应用程序中,首先需要将 XWSAError.h 添加到您的项目中。XWSAError.h 会自动链接到 XWSAError.lib,所以您只需要将 XWSAError.lib 目录添加到您的项目中(在 VC 6.0 中,转到 Project | Settings | Link | Input,并将目录添加到 Additional Library Path)。最后,在您要调用函数的模块中插入以下行:

#include "XWSAError.h"

然后,确保 XWSAError.dll 与应用程序的 exe 文件位于同一目录中。

如何在 Visual Basic 中使用

要使 XWSAError.dll 在 VB 应用程序中工作,首先要做的是使用 __stdcall 调用约定定义所有函数:

XWSAERROR_API int __stdcall XWSA_GetErrorString(int nErrorCode, 
                             TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetErrorCode(const TCHAR * lpszErrorString);
XWSAERROR_API int __stdcall XWSA_GetErrorStringSize();
XWSAERROR_API int __stdcall XWSA_GetShortDescription(int nErrorCode, 
                             TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetShortDescriptionSize();
XWSAERROR_API int __stdcall XWSA_GetLongDescription(int nErrorCode, 
                            TCHAR * lpszBuf, int nBufSize);
XWSAERROR_API int __stdcall XWSA_GetLongDescriptionSize();

这与 XWSAERROR_API 宏中使用的 __declspec(dllexport) 一起,会导致导出的函数具有修饰名称(如 dumpbin 所示)。

ordinal hint RVA      name

      1    0 0000100F _XWSA_GetErrorCode@4
      2    1 00001019 _XWSA_GetErrorString@12
      3    2 0000101E _XWSA_GetErrorStringSize@0
      4    3 00001014 _XWSA_GetLongDescription@12
      5    4 00001023 _XWSA_GetLongDescriptionSize@0
      6    5 00001028 _XWSA_GetShortDescription@12
      7    6 00001032 _XWSA_GetShortDescriptionSize@0

这意味着 VB 程序在调用任何这些函数之前必须别名导出的名称。这很麻烦,但我们可以通过添加一个 **模块定义文件**(XWSAError.def)来避免这个问题:

; XWSAError.def - module definition file
;
; The EXPORTS in this file remove the decoration from the function names,
; and so allow Visual Basic programs to call the XWSAError functions using
; the same names as VC++ programs.

LIBRARY XWSAError

DESCRIPTION "Winsock error lookup"

EXPORTS
  XWSA_GetErrorCode
  XWSA_GetErrorString
  XWSA_GetErrorStringSize
  XWSA_GetLongDescription
  XWSA_GetLongDescriptionSize
  XWSA_GetShortDescription
  XWSA_GetShortDescriptionSize

现在,未修饰的函数名称被导出:

ordinal hint RVA      name

      1    0 0000100F XWSA_GetErrorCode
      2    1 00001019 XWSA_GetErrorString
      3    2 0000101E XWSA_GetErrorStringSize
      4    3 00001014 XWSA_GetLongDescription
      5    4 00001023 XWSA_GetLongDescriptionSize
      6    5 00001028 XWSA_GetShortDescription
      7    6 00001032 XWSA_GetShortDescriptionSize

现在 VB 程序可以在没有任何额外工作的情况下调用这些函数,如下面的代码片段所示(一个 VB 示例程序包含在下载中):

Private Declare Function XWSA_GetShortDescriptionSize Lib "XWSAError.dll" () _
                                                                    As Integer
Private Declare Function XWSA_GetShortDescription Lib "XWSAError.dll"
 (ByVal nerror%, ByVal sd$, ByVal sdsize%) As Integer

Private Sub Command1_Click()

    Dim nSize As Integer, rc As Integer, error As Integer
    Dim ErrorCode As String, ShortDesc As String

    nSize = XWSA_GetShortDescriptionSize()
    ShortDesc = String$(nSize, Chr$(0))
    ErrorCode = Form1.Text1.Text
    error = ErrorCode
    rc = XWSA_GetShortDescription(error, ShortDesc, Len(ShortDesc))
    Form1.Text2.Text = "XWSA_GetShortDescription() returned:  " + ShortDesc

End Sub

有关在 VB 中使用 DLL 函数的更多信息,请参阅 Q142840: Visual Basic Requirements for Exported DLL Functions

演示应用程序

演示应用程序在您输入错误代码时显示各种字符串。

screenshot

修订历史

版本 1.0 - 2005 年 1 月 6 日

  • 首次公开发布。

用法

此软件已发布到公共领域。您可以随心所欲地使用它,但不得出售此源代码。如果您修改或扩展它,请考虑将新代码发布到此处供大家共享。此软件按“原样”提供,不附带任何明示或暗示的保证。我对本软件可能造成的任何损害或业务损失概不负责。

© . All rights reserved.