如何解决IO 完成端口和 WSASend
先抱歉,但请解释一下,如何将 IOCP 与 WSASend 一起使用 - 例如,向服务器发送一条简单的消息并接收来自它的响应。
我正在这样做:
- 创建完成端口
- 为完成端口创建线程
- 我创建了一个带有 Overlaped 标志的 WSASocket。
- 我使用 WSAConnect 与远程服务器建立连接
- 我将套接字绑定到完成端口。
- 我通过调用 WSASend 函数向服务器发送消息。
像这样:
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,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,(LPTHREAD_START_ROUTINE)&My_func_for_Thread,My_handle_IOCP,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,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);
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------Bind socket and port--------------------------------------------------------
My_handle_Create_IOCP = CreateIoCompletionPort((HANDLE)my_WSASocketA,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,&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]);
}
//---------------------------------------------------------
}
但是,GetQueuedCompletionStatus 总是返回 998 - 对内存位置的无效访问。 哪些内存被禁用访问?我做错了什么?
解决方法
您的代码有几个问题。
您的 My_func_for_Thread()
函数的签名错误,无法与 CreateThread()
一起使用。编译器不会抱怨,因为您正在使用类型转换来使编译器免于失败。
您正在向 lpCompletionKey
的 GetQueuedCompletionStatus()
参数传递一个未初始化指针。它需要一个指向有效 ULONG_PTR
变量的指针以供其写入。
WSAOVERLAPPED
需要在内存中保持活动状态,直到从 IOCP 队列中检索到其最终状态。但是您的线程休眠的时间比 main()
的运行时间长得多。您应该动态分配 WSAOVERLAPPED
,然后在收到其状态时将其释放。
尝试更像这样的事情:
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,&My_func_for_Thread,My_handle_IOCP,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,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;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。