【问题标题】:problem with socket programming in c\c++c\c++中的socket编程问题
【发布时间】:2009-03-21 17:06:29
【问题描述】:
#include "stdafx.h"
#include <windows.h>
#include <winsock.h>
#include <stdio.h>

int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR IpCmdLine,int nCmdShow)
{
    WSADATA ws;
    char buf[100];

    WSAStartup(0x0101,&ws);

    sprintf(buf,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));
    MessageBox(0,buf,"info",0);
    WSACleanup();
    return 0;
}

该程序用于获取计算机中可用wsock版本的信息。 我不明白为什么程序中包含“stdafx.h”。 APIENTRY的意义是什么?我们不能改用 _stdcall 吗? 我也无法在 VC++ 中编译它。代码有什么问题?

以下是执行程序时的错误,编译时没有错误。

--------------------Configuration: sa - Win32 Debug--------------------
Linking...
sa.obj : error LNK2001: unresolved external symbol _WSACleanup@0
sa.obj : error LNK2001: unresolved external symbol _WSAStartup@8
LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/sa.exe : fatal error LNK1120: 3 unresolved externals
Error executing link.exe.

sa.exe - 4 error(s), 0 warning(s)

【问题讨论】:

  • 请详细说明您遇到的问题!

标签: c++ c sockets winsock


【解决方案1】:
  1. stdafx用于在VC++中实现precompiled headers。您可以将 windows.h 和 winsock.h 等库头文件放在那里,每次修改 stdafx.h 时它们只会编译一次。

  2. APIENTRY 通常只是 __stdcall 的定义,但有时它定义为空白(例如,如果不支持 __stdcall)。这是为了让你的代码更便携。

  3. 如果没有您遇到的实际错误,我将无法提供太多帮助。但我的第一个猜测是你的构建中有 unicode,它抱怨 MessageBoxW 不接受 char[100] 作为参数。在这种情况下,要么处处使用宽字符,要么关闭 unicode,或者使用 MessageBoxA 显式使用 ASCII 版本。

编辑:

现在有了错误,这很容易。在项目属性 -> 链接器 -> 输入 -> 附加依赖项下,添加 ws2_32.lib。这样你就可以把 Winsock 函数链接进去了。

缺少的 _main 表示您正在将应用程序构建为控制台应用程序,而不是 Windows 应用程序。返回项目属性 -> 链接器 -> 系统并将子系统设置为 Windows (/Subsystem:Windows) 而不是控制台。否则,只需将 WinMain 重命名为 int main()(确保删除 APIENTRY)。

另外,如果您使用的是 MSVC++,您不妨使用更安全的 sprintf_s:

sprintf_s(buf,100,"%d.%d",HIBYTE(ws.wVersion),LOBYTE(ws.wVersion));

【讨论】:

  • 打败我。这就是我要说的。 :)
  • 我仍然收到此错误--------配置:sa - Win32 调试--------- ----------- 正在链接... LINK:致命错误 LNK1104:无法打开文件“odbccp32.libwin32.lib” 执行链接.exe 时出错。 sa.exe - 1 个错误,0 个警告
  • 您在选项中的某个位置删除了 odbccp32.lib 和 win32.lib 之间的分号
  • 您最好在不做任何更改的情况下开始一个新项目。
  • 有一个 .在项目设置链接选项卡和对象/libraru 模块中的 odbccp32.lib 和 win32.lib 之间
【解决方案2】:

至于错误:您需要链接到 ws2_32.lib 库。您可以通过两种方式做到这一点:

  1. 将其添加到项目属性 -> 链接器 -> 输入 -> “其他库”(不要忘记为调试和发布配置执行此操作)。
  2. 在你的头文件中添加这个编译器指令:

    #pragma comment(lib, "ws2_32.lib")

我更喜欢第二种方法,因为您所做的更改在源代码中可见,而不是隐藏在项目选项的深处。

至于 APIENTRY 和类似的定义——这只是一种方便,比如返回 NULL 而不是 0 来指出你没有返回任何东西而不是数字零。使代码更易于阅读和理解。

【讨论】:

    【解决方案3】:

    stdafx 与 Visual Studio 中的预编译头文件有关。它与套接字没有任何特定关系。

    APIENTRY 与 WinMain 的调用约定有关,同样它不应该与套接字有任何关系。

    发布错误。

    【讨论】:

      【解决方案4】:

      就链接器错误而言,您应该链接到 wsock32.lib。

      【讨论】:

        【解决方案5】:

        如果链接器抱怨它找不到 _main,这意味着它试图将您的程序链接为控制台应用程序,这意味着您应该定义 main() 而不是 WinMain()。如果您有 WinMain(),您可能应该将您的应用程序构建为 Windows 应用程序。

        【讨论】:

          【解决方案6】:

          尝试下一个
          打开项目属性,选择链接器属性,选择输入子项在附加依赖项中添加Ws2_32.lib 不要忘记对所有项目配置执行相同的操作。
          看来你也需要改变使用 int main() 而不是 WinMain(...)

          stdafx.h - 通常表示预编译头文件 VC++ 项目
          APIENTRY - 调用约定。在您的情况下,它是 __stdcall,但有时可能意味着其他。

          【讨论】:

            猜你喜欢
            • 2014-10-06
            • 2012-02-11
            • 2011-02-02
            • 2011-07-19
            • 1970-01-01
            • 2011-07-31
            • 1970-01-01
            • 2017-01-29
            • 1970-01-01
            相关资源
            最近更新 更多