【问题标题】:LNK2019: Unresolved external symbolLNK2019:未解析的外部符号
【发布时间】:2011-08-31 00:23:27
【问题描述】:

我见过很多其他类似的问题,但在他们的帮助下我无法解决这个问题。我知道这是一个链接问题,但据我所知,我已经理顺了链接。

我正在编写一个聊天服务器/客户端(在 this article 的帮助下)。

我已经定义了一个类来保存服务器函数,并有一个处理所有包含的头文件。

这是头文件:

#include <windows.h>
#include <winsock.h>
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include "resource1.h"


class ChatServer
{
    public: int InitServer(HINSTANCE hInst);

    public: void ReportError(int errorCode, const char *whichFunc);
};

这是实际的服务器“类”:

#include "server.h"
#define NETWORK_ERROR -1
#define NETWORK_OK     0
//Keeps stuff for the server    
int ChatServer::InitServer(HINSTANCE hInst)
    {
        WORD sockVersion;
        WSADATA wsaData;
        int nret;

        sockVersion = MAKEWORD(1,1); //Version 1.1

        //Init winsock
        WSAStartup(sockVersion, &wsaData);

        //Create listening socket
        SOCKET listeningSocket;

        //AFINET - Go over TCP
        //SOCK_STREAM - Stream oriented socket
        //IPPROTO_TCP - Use tcp rather than udp
        listeningSocket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP);

        if(listeningSocket == INVALID_SOCKET)
        {
            nret = WSAGetLastError(); //Get error detail
            ReportError(nret, "socket()");

            WSACleanup();

            return NETWORK_ERROR;
        }

        SOCKADDR_IN serverInfo;

        serverInfo.sin_family = AF_INET;
        serverInfo.sin_addr.s_addr = INADDR_ANY;
        serverInfo.sin_port = htons(1337); 

        //Bind the socket to local server address.
        nret = bind(listeningSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));

        if(nret == SOCKET_ERROR)
        {
            nret = WSAGetLastError();
            ReportError(nret, "bind()");
            WSACleanup();
            return NETWORK_ERROR;
        }

        //Make socket listen
        nret = listen(listeningSocket, 10); //Up to 10 connections at the same time.

        if(nret = SOCKET_ERROR)
        {
            nret = WSAGetLastError();
            ReportError(nret, "listen()");
            WSACleanup();
            return NETWORK_ERROR;
        }

        //Wait for client
        SOCKET theClient;
        theClient = accept(listeningSocket, NULL, NULL);

        if(theClient == INVALID_SOCKET)
        {
            nret = WSAGetLastError();
            ReportError(nret, "accept()");
            WSACleanup();
            return NETWORK_ERROR;
        }

        //Send and receive from the client, and finally,
        closesocket(theClient);
        closesocket(listeningSocket);

        //shutdown
        WSACleanup();
        return NETWORK_OK;
    }



void ChatServer::ReportError(int errorCode, const char *whichFunc)

    {

       char errorMsg[92];                   // Declare a buffer to hold
                                            // the generated error message
       ZeroMemory(errorMsg, 92);            // Automatically NULL-terminate the string
       // The following line copies the phrase, whichFunc string, and integer errorCode into the buffer
       sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);



       MessageBox(NULL, errorMsg, "socketIndication", MB_OK);

    }

最后,带有程序入口方法的 main.cpp 文件调用“ChatServer::InitServer(g_hInst)”。它很大,所以我省略了它,但如果需要,我也会发布它。

我收到的错误消息类似于以下错误消息,但它们都说明与 winsockets API 相关的 api 函数存在问题:

Error   3   error LNK2019: unresolved external symbol _closesocket@4 referenced in function "public: int __thiscall ChatServer::InitServer(struct HINSTANCE__ *)" (?InitServer@ChatServer@@QAEHPAUHINSTANCE__@@@Z)  

正如我之前所说,我认为这个问题与编译器误解了如何处理应该链接到 winsock.h 的“closesocket”等函数有关。

感谢您的任何建议,感谢您阅读所有这些废话:)

【问题讨论】:

  • 你为什么不用winsock2.h?
  • 你链接wininet.lib和ws2_32.lib了吗?
  • 你不需要在每个成员函数声明的前面加上public。列出访问说明符后,后面的所有内容都将具有相同的访问权限,直到您列出不同的访问说明符为止。
  • 这实际上是 Drahakar 和 stinj 上面所说的组合。将 #include 作为要包含的第一个头文件(在 Windows.h 之前,winsock2.h 无论如何都包含)。然后从项目设置中将 ws2_32.lib 添加到您的链接库中。 Praetorian 对“公共”的看法也是正确的。
  • @selbie;你应该回答这个问题,我做了你所说的并摆脱了错误。谢谢。

标签: c++ winapi winsock


【解决方案1】:

这些链接器错误总是相同的:您正在使用链接器找不到的符号。您需要告诉链接器链接到包含这些符号的库。

正如我之前所说,我认为这个问题与 编译器误解了如何处理类似的函数 “closesocket”应该链接到winsock.h。

不,closesocket 未链接到 winsock.h。 winsock.h 是头文件,而不是库。它可能包含closesocket 的声明,这对编译器来说没问题,但链接器确实需要知道该函数的代码在哪里,以便将您的程序链接到它。

不过,您可能应该使用 winsock2.h 而不是 winsock.h。 Windows Sockets API 2.0 始于 1994 年,版本 1 早已过时。

你可以在this function's documentation的底部看到它所在的库是ws2_32.lib。

【讨论】:

    【解决方案2】:

    你的类可以这样定义:

    class ChatServer
    {
    public:
        int InitServer(HINSTANCE hInst);
        void ReportError(int errorCode, const char *whichFunc);
    };
    

    但是,您的错误是由于不包括库输入引起的。在您的项目输入行中添加对 winsock 库的依赖项,还可以考虑使用 winsock2.h。

    供参考:http://msdn.microsoft.com/en-us/library/ms737629(v=vs.85).aspx

    【讨论】:

      【解决方案3】:

      仅包含 .h 文件不会导致链接到实现函数的实际代码。.h 文件告诉编译器函数存在于某处,以及它们的签名是什么。您仍然必须使实际实现该函数的库对链接器可用。

      【讨论】:

        猜你喜欢
        • 2014-11-07
        • 2013-06-01
        • 2022-01-06
        • 2014-09-19
        • 2012-12-17
        • 1970-01-01
        • 1970-01-01
        • 2019-05-27
        • 2012-10-31
        相关资源
        最近更新 更多