简体   繁体   中英

Developing with WinSock2, error with CreateThread() function

I begin to develop my tool, which works with net at the TCP level, and have got the following problem:

  • Creating thread for accept() function of Winsock

I have googled and looked for the references and evereywhere there is info about creating new thread:

  • It must have DWORD WINAPI (unsigned long __stdcall) in prefix
  • It must accept LPVOID argument

And such function will be used as the 3rd argument in CreateThread() function as LPTHREAD_START_ROUTINE structure.

But I have got the next error after compiling:

(131) : error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (__stdcall Net::* )(LPVOID)' to 'LPTHREAD_START_ROUTINE'

Here is my code:

#include <iostream>
#include <Windows.h>

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

typedef struct Header
{
friend struct Net;

private:
    WORD wsa_version;
    WSAData wsa_data;

    SOCKET sock;
    SOCKADDR_IN service;

    char *ip;
    unsigned short port;

public:
    Header(void)
    {
        wsa_version = 0x202;

        ip = "0x7f.0.0.1";
        port = 0x51;

        service.sin_family = AF_INET;
        service.sin_addr.s_addr = inet_addr(ip);
        service.sin_port = htons(port);
    }

} Header;

typedef struct Net
{
private:
    int result;

    void WSAInit(WSAData *data, WORD *wsa_version)
    {
        result = WSAStartup(*wsa_version, &(*data));

        if(result != NO_ERROR)
        {
            std::cout << "WSAStartup() failed with the error: " << result << std::endl;
        }
        else
        {
            std::cout << (*data).szDescription << " " << (*data).szSystemStatus << std::endl;
        }
    }

    void SocketInit(SOCKET *my_socket)
    {
        (*my_socket) = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

        if((*my_socket) == INVALID_SOCKET)
        {
            std::cout << "Socket initialization failed with the error: " << WSAGetLastError() << std::endl;
            WSACleanup();
        }
        else
        {
            std::cout << "Socket initialization successful!" << std::endl;
        }
    }

    void SocketBind(SOCKET *my_socket, SOCKADDR_IN *service)
    {
        result = bind((*my_socket), (SOCKADDR*)&(*service), sizeof(*service));

        if(result == SOCKET_ERROR)
        {
            std::cout << "Socket binding failed with the error: " << WSAGetLastError() << std::endl;
            closesocket((*my_socket));
            WSACleanup();
        }
        else
        {
            std::cout << "Socket binding successful!" << std::endl;
        }

        result = listen(*my_socket, SOMAXCONN);

        if(result == SOCKET_ERROR)
        {
            std::cout << "Socket listening failed with the error: " << WSAGetLastError() << std::endl;
        }
        else
        {
            std::cout << "Listening to the socket..." << std::endl;
        }
    }

    void SocketAccept(SOCKET *my_socket)
    {
        SOCKET sock_accept = accept((*my_socket), 0, 0);

        if(sock_accept == INVALID_SOCKET)
        {
            std::cout << "Accept failed with the error: " << WSAGetLastError() << std::endl;
            closesocket(*my_socket);
            WSACleanup();
        }
        else
        {
            std::cout << "Client socket connected!" << std::endl;
        }

        char data[0x400];
        result = recv(sock_accept, data, sizeof(data), 0);
    }

    DWORD WINAPI Threading(LPVOID lpParam)
    {
        SOCKET *my_socket = (SOCKET*)lpParam;
        SocketAccept(my_socket);
    }

public:
    Net(void)
    {
        Header *obj_h = new Header();

        WSAInit(&obj_h->wsa_data, &obj_h->wsa_version);

        SocketInit(&obj_h->sock);
        SocketBind(&obj_h->sock, &obj_h->service);

        HANDLE thrd = CreateThread(NULL, 0, &Net::Threading, &obj_h->sock, 0, NULL);

        delete &obj_h;
    }
} Net;

int main(void)
{
    Net *obj_net = new Net();

    delete &obj_net;

    return 0;
}

You cant use C++ non-static member function.

Use a static one

Nestal's answer is correct - CreateThread expects a function, not a method. That said there are so many other things wrong with this sample I don't know if just leaving it there is the responsible thing to do.

First off, the coding style is just bizarre: The sample is nominally written in C++, but actually looks like a C program. If you are going to bother switching from C to C++, then be aware that using "friend" like that, is a strong hint that you are 'doing it wrong'.

The strange style of directly passing references to attributes of friend classes around serves to hide actual code issues: Even once its building its going to fail a lot as there are numerous race conditions: The socket, passed to the thread as a reference: &obj_h->sock will be deleted while Threading is still running. Even if it wasn't deleted, it (and any variable that is referenced from multiple threads) should be qualified as volatile to ensure the compiler doesn't optimize out actually persisting the variable into memory.

Even once you have made the thread proc 'static', passed the parameters safely, sorted out the race conditions, and correctly volatile qualified any shared variables, you will need to add thread synchronization to guard access to shared variables. Again - the code style presented, of directly passing references to values, makes it difficult to know when variables might be read and written from different threads - making a synchronization strategy difficult to implement consistently.

Good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM