LNK2019:未解析的外部符号
我见过很多类似的问题,但在他们的帮助下我无法解决这个问题。我知道这是一个链接问题,但从我所看到的来看,我已经理顺了链接。
我正在编写一个聊天服务器/客户端(在本文的帮助下) 。
我定义了一个类来保存服务器函数,并有一个处理所有包含内容的头文件。
这是头文件:
#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);
}
最后,带有程序调用“ChatServer::InitServer(g_hInst)”入口方法的 main.cpp 文件。它相当大,所以我省略了它,但如果需要的话我也会发布它。
我收到的错误消息类似于下面的错误消息,但它们都说明了与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)
正如我之前所说,我相信这个问题与编译器误解如何处理类似的函数有关“closesocket”应该链接到winsock.h。
感谢您的任何建议,也感谢您阅读所有这些胡言乱语:)
I've seen plenty of other questions like this but I just couldn't figure this problem out with the help of them. I've understood that it's a linking problem but from what I can see, I've got the linking straightened out.
I'm writing a chat server/client (with the help of this article).
I've defined a class to hold the server functions and have a header-file that handles all the includes.
This is the header file:
#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);
};
This is the actual server "class":
#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);
}
And lastly, the main.cpp file with the entry-method for the program calls "ChatServer::InitServer(g_hInst)". It's pretty big so I omitted it but if it's needed I'll post it aswell.
The error messages I'm getting are like the one below but they all state problems with the api-functions related to winsockets API:
Error 3 error LNK2019: unresolved external symbol _closesocket@4 referenced in function "public: int __thiscall ChatServer::InitServer(struct HINSTANCE__ *)" (?InitServer@ChatServer@@QAEHPAUHINSTANCE__@@@Z)
As I stated before, I believe this problem has something to do with the compiler misunderstanding what to do with functions like "closesocket" that should be linked to winsock.h.
Thanks for any advice at all and thanks for reading all of this gibberish :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这些链接器错误始终是相同的:您使用的是链接器找不到的符号。您需要告诉链接器链接包含这些符号的库。
不,
closesocket
未链接到winsock.h。 winsock.h 是一个头文件,而不是一个库。它可能包含closesocket
声明,这对编译器来说没问题,但链接器确实需要知道该函数的代码在哪里,以便将您的程序链接到它。不过,您可能应该使用winsock2.h 而不是winsock.h。 Windows Sockets API 2.0 可以追溯到 1994 年,版本 1 早已过时。
您可以在此函数的文档底部看到该函数所在的库驻留在ws2_32.lib。
These linker errors are always the same: you're using a symbol that the linker cannot find. You need to tell the linker to link with the libraries that contain those symbols.
No,
closesocket
is not linked to winsock.h. winsock.h is a header file, not a library. It may contain a declaration ofclosesocket
and that's ok for the compiler, but the linker really needs to know where the code of that function is so it can link your program to it.You should probably be using winsock2.h instead of winsock.h, though. The Windows Sockets API 2.0 dates from 1994, and version 1 is long obsolete.
You can see at the bottom of this function's documentation that the library where it resides is ws2_32.lib.
您的类可以这样定义:
但是您的错误是由于不包含库输入而引起的。在您的项目输入行中添加对winsock库的依赖项,还可以考虑使用winsock2.h。
供参考:http://msdn.microsoft.com /en-us/library/ms737629(v=vs.85).aspx
Your class can be defined like so:
However you're error is caused by not including the library input. On your project input line add the dependency on winsock library also consider using winsock2.h.
For reference: http://msdn.microsoft.com/en-us/library/ms737629(v=vs.85).aspx
仅包含 .h 文件不会导致链接实现函数的实际代码。.h 文件告诉编译器这些函数存在于某处,以及它们的签名是什么。您仍然必须使实际实现该函数的库可供链接器使用。
Just including the .h file does not cause the actual code that implements the functions to be linked in. The .h file tells the compiler that the functions exist somewhere, and what their signature is. You still have to make the library where the function is actually implemented available to the linker.