Reputation: 448
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:
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
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