包含线程后的C++套接字错误WSANEOTSOCK(10038)

包含线程后的C++套接字错误WSANEOTSOCK(10038),c++,multithreading,sockets,winsock,winsockets,C++,Multithreading,Sockets,Winsock,Winsockets,我在客户端和服务器之间创建了TCP套接字连接 我有必要使用线程,因为我从另一个进程获取x和y坐标,并使用OpenGL绘制这些值 我想到的唯一方法是为OpenGL绘图创建线程,并使用主线程通过套接字接收坐标 在添加include之前,我的服务器端工作得很好,所以我不知道问题出在哪里,为什么在使用套接字时不能使用线程 包括线程后,调用recv后,我得到错误: WSAENOTSOCK 10038 使用WSAGetLastError 我认为代码太长了,我无法发布它,所以我可以复制其中一些必要的部分 编辑

我在客户端和服务器之间创建了TCP套接字连接

我有必要使用线程,因为我从另一个进程获取x和y坐标,并使用OpenGL绘制这些值

我想到的唯一方法是为OpenGL绘图创建线程,并使用主线程通过套接字接收坐标

在添加include之前,我的服务器端工作得很好,所以我不知道问题出在哪里,为什么在使用套接字时不能使用线程

包括线程后,调用recv后,我得到错误:

WSAENOTSOCK 10038

使用WSAGetLastError

我认为代码太长了,我无法发布它,所以我可以复制其中一些必要的部分

编辑:创建套接字并等待连接的代码

// Inicijaliziraj winsock
WSADATA wsData;
WORD ver = MAKEWORD(2, 2);

int wSocket = WSAStartup(ver, &wsData);
if (wSocket != 0) {
    cerr << "Problem with initialization of Winsock, exiting!" << endl;
    return;
}

// Create a socket
SOCKET listening = socket(AF_INET, SOCK_STREAM, 0);
if (listening == INVALID_SOCKET) {
    cerr << "Unable to create a socket! Quitting" << endl;
    return;
}

// Bind the ip address and port to a socket
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(54000);
hint.sin_addr.S_un.S_addr = INADDR_ANY; // Could also use inet_pton

bind(listening, (sockaddr*)&hint, sizeof(hint));

// Tell winsock socket is for listening
listen(listening, SOMAXCONN);

// Wait for a connection
sockaddr_in client;
int clientSize = sizeof(client);

SOCKET clientSocket = accept(listening, (sockaddr*)&client, &clientSize);
/*
if (clientSocket == INVALID_SOCKET) {
cerr << "Unable to connect to client socket, Quitting!" << endl;
return;
}*/

char host[NI_MAXHOST];              // Client's remote name
char service[NI_MAXHOST];           // Service (PORT) the client is connected on

ZeroMemory(host, NI_MAXHOST);       // Could use memset(host, 0, )
ZeroMemory(service, NI_MAXHOST);

if (getnameinfo((sockaddr*)&client, sizeof(client), host, NI_MAXHOST, service, NI_MAXSERV, 0) == 0)
{
    cout << host << " connected on port " << service << endl;
}
else
{
    inet_ntop(AF_INET, &client.sin_addr, host, NI_MAXHOST);
    cout << host << " connected on port " << ntohs(client.sin_port) << endl;
}

// Close listening socket
closesocket(listening);

// While loop: accept and echo message back to client
char buf[4096];

//Opens new thread with canvas because otherwise while loop for recieving will block drawing
//std::thread t1(setDrawing, &iArgc, cppArgv);

while (true) {
    ZeroMemory(buf, 4096);

    // Wait for client to send data
    int bytesRecieved = recv(clientSocket, buf, 4096, 0);
    if (bytesRecieved == SOCKET_ERROR) {
        int err = WSAGetLastError();
        cerr << "Error in recv(). Quitting!" << endl;
        break;
    }
    if (bytesRecieved == 0) {
        cout << "Client disconnected " << endl;
        break;
    }
在添加include之前,我的服务器端工作得很好,所以我不知道问题出在哪里,为什么在使用套接字时不能使用线程

<> P>一个值得注意的事情是C++的STL头。如果您的代码碰巧有一个using名称空间std;语句时,套接字代码可能会调用STL的std::bind函数而不是WinSock的bind函数,这将导致侦听失败,并出现WSAEINVAL错误。因为您没有对绑定或侦听调用进行任何错误处理,所以您没有检查它。所以要意识到这一点。避免使用名称空间std;语句,或者改为调用WinSock的bind as::bind。并始终对API调用执行错误处理


您还注释了accept上的错误处理。如果绑定和侦听失败,so将接受,导致它返回无效的\u套接字。这可以解释为什么在recv上出现WSAENOTSOCK错误。

WSAENOTSOCK:nonsocket上的套接字操作。尝试对非套接字的对象执行操作。套接字句柄参数未引用有效的套接字,或者对于select,fd_集的成员无效。你能提供从创建套接字到调用recv的代码吗?我编辑了我的帖子,代码现在在里面。你为什么要注释掉clientSocket上的检查?绑定和侦听返回什么值?您在任何时候都有使用名称空间std吗?使用主线程通过套接字接收坐标-除了GUI更新和用户交互之外,不要使用主线程。如果您打算使用线程来准备OpenGL图形,那么您也可以而且应该使用线程或IOCP来进行套接字操作,这样您就不会以任何方式阻碍主线程,除非您切换到基于窗口消息的套接字I/O调用,我不推荐这样做。