Optimus1
Optimus1

Reputation: 448

IO Completion Ports and WSASend

Sorry in advance, but please explain, how to use IOCP with WSASend - for example, to send a simple message to the server and receive a response from it.

I am doing this:

  1. Create completion port
  2. Create threads for the completion port
  3. I create a WSASocket, with the Overlaped flag.
  4. I establish a connection with a remote server using WSAConnect
  5. I bind the socket to the completion port.
  6. I send a message to the server - by calling the WSASend function.

Like this:

void My_func_for_Thread(HANDLE iocp)
{

    DWORD my_DWORD;
    PULONG_PTR   my_CompletionKey;

    WSAOVERLAPPED* my_WSAOVERLAPPED_1;


    int my_GetLastError;


    while (1)
    {

        BOOL my_BOOL_GetQueuedCompletionStatus = GetQueuedCompletionStatus(iocp, &my_DWORD, my_CompletionKey, &my_WSAOVERLAPPED_1, INFINITE);


        my_GetLastError = GetLastError();

   
            if (my_BOOL_GetQueuedCompletionStatus == FALSE)
            {
                std::cout << "GetQueuedCompletionStatus== FALSE" << std::endl;
            }

      }
}

int main()
    {
    
    //-------------------------------------------------------------------Create port IO-------------------------------------------------------------
    
        int Number_Threads = 4;  
    
        HANDLE My_handle_IOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, Number_Threads);
    
    //------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
    //-------------------------------------------------------------------Create thread for IOCP-------------------------------------------------------
    
        std::vector<HANDLE>my_vector_Thread;
    
    
        for (int i = 0; i < Number_Threads; i++)
        {
            my_vector_Thread.push_back(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)&My_func_for_Thread, My_handle_IOCP, 0, 0));
        }
    
    
    //---------------------------------------------------------------------------------------------------------------------------------------------------
    
   
    
    //-------------------------------------------------------------------Initialization Winsock-----------------------------------------------------------
    
    WORD my_version_Winsock = MAKEWORD(2, 2); 
    
    WSADATA my_wsadata_struct; 
    
    int my_WSAStartup = WSAStartup(my_version_Winsock, &my_wsadata_struct);
    
    //------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
    //-------------------------------------------------------------------Create WSASocket-----------------------------------------------------------------
    
    SOCKET my_WSASocketA = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    
    //--------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
    //-------------------------------------------------------------------
    
        std::string myString_IP = "XX.XXX.XX.XXX";
    
    //--------------------------------------------------------------------------
    
        sockaddr my_sockaddr;                 
    
        my_sockaddr = { 0 };                                            
        my_sockaddr.sa_family = 2;                                          // AF_INET.
        inet_pton(AF_INET, myString_IP.c_str(), &my_sockaddr.sa_data[2]);   
        my_sockaddr.sa_data[1] = 80;                                     //http port
    
        //--------------------------------------------------------------------------
    

    
        int status_WSAConnect = WSAConnect(my_WSASocketA, &my_sockaddr, sizeof(my_sockaddr), NULL, NULL, NULL, NULL);
    
    
    //-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
    
    //-------------------------------------------------------------------Bind socket and port--------------------------------------------------------
    
        My_handle_Create_IOCP = CreateIoCompletionPort((HANDLE)my_WSASocketA, My_handle_IOCP, NULL, 0);
    
    //-------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
    
    //-------------------------------------------------------------------Send message to serever with WSASend-----------------------------------
    
             WSABUF my_WSABUF;
    
             std::string request_text_string = "GET / HTTP/1.1\r\nHost: government.ru\r\nConnection: keep-alive\r\n\r\n";
    
    
             my_WSABUF.buf = &request_text_string[0];
             my_WSABUF.len = request_text_string.size();
    
    
             WSAOVERLAPPED my_WSAOVERLAPPED;
             my_WSAOVERLAPPED = { 0 };
    
    
    
             int my_WSASend =  WSASend(my_WSASocketA, &my_WSABUF, 1, NULL, 0, &my_WSAOVERLAPPED, NULL);
    
    
                     if (my_WSASend == SOCKET_ERROR)
             {
                       std::cout << "WSASend == SOCKET_ERROR:" std::endl;
                     }
    
                      if (my_WSASend == 0)
             {
                       std::cout << "WSASend == 0: no error" std::endl;
                     }
    
    
    //-----------------------------------------------------------------------------------------------------------------------------------------------------------
    
    
    
             Sleep(10000);
    
    
             //---------------------------------------------------------
             for (int i = 0; i < Number_Threads; i++)
             {
                 CloseHandle(my_vector_Thread[i]);
             }
             //---------------------------------------------------------
    
    }

But, GetQueuedCompletionStatus always return 998 - Invalid access to memory location. Which memory is the disabled access to? What am I doing wrong ?

Upvotes: 0

Views: 593

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596256

There are several problems with your code.

Your My_func_for_Thread() function has the wrong signature for use with CreateThread(). The compiler is not complaining because you are using a typecast to silence the compiler from failing.

You are passing an uninitialized pointer to the lpCompletionKey parameter of GetQueuedCompletionStatus(). It expects a pointer to a valid ULONG_PTR variable for it to write to.

The WSAOVERLAPPED needs to remain active in memory until its final status is retrieved from the IOCP queue. But your thread is sleeping much longer than your main() is running. You should allocate the WSAOVERLAPPED dynamically, and then free it when its status is received.

Try something more like this instead:

DWORD WINAPI My_func_for_Thread(LPVOID lpParameter)
{
    HANDLE iocp = (HANDLE) lpParameter;
    DWORD my_DWORD;
    ULONG_PTR  my_CompletionKey;
    WSAOVERLAPPED* my_WSAOVERLAPPED_1;
    DWORD my_GetLastError;

    while (TRUE)
    {
        BOOL my_BOOL_GetQueuedCompletionStatus = GetQueuedCompletionStatus(iocp, &my_DWORD, &my_CompletionKey, (LPOVERLAPPED*) &my_WSAOVERLAPPED_1, INFINITE);

        my_GetLastError = GetLastError();

        if (my_BOOL_GetQueuedCompletionStatus)
        {
            delete my_WSAOVERLAPPED_1;
        }
        else
        {
            std::cout << "GetQueuedCompletionStatus == FALSE" << std::endl;
        }
    }

    return 0;
}

int main()
{
    ...

    for (int i = 0; i < Number_Threads; i++)
    {
        HANDLE hThread = CreateThread(NULL, 0, &My_func_for_Thread, My_handle_IOCP, 0, NULL);
        if (hThread)
            my_vector_Thread.push_back(hThread);
    }

    ...

    std::string request_text_string = "GET / HTTP/1.1\r\nHost: government.ru\r\nConnection: keep-alive\r\n\r\n";

    WSABUF my_WSABUF;
    my_WSABUF.buf = &request_text_string[0];
    my_WSABUF.len = request_text_string.size();

    WSAOVERLAPPED *my_WSAOVERLAPPED = new WSAOVERLAPPED;
    *my_WSAOVERLAPPED = { 0 };

    int my_WSASend =  WSASend(my_WSASocketA, &my_WSABUF, 1, NULL, 0, my_WSAOVERLAPPED, NULL);

    // wait for request to finish...
    // wait for response to arrive...
    // close socket...
    // wait for threads to terminate...

    ...

    for (size_t i = 0; i < my_vector_Thread.size(); i++)
    {
        CloseHandle(my_vector_Thread[i]);
    }

    return 0;
}       

Upvotes: 1

Related Questions