[英]IOCP C++ TCP client
I am having some trouble implementing TCP IOCP client. 我在实施TCP IOCP客户端时遇到了一些麻烦。 I have implemented kqueue on Mac OSX so was looking to do something similar on windows and my understanding is that IOCP is the closest thing.
我已经在Mac OSX上实现了kqueue,所以我希望在Windows上做类似的事情,我的理解是IOCP是最接近的东西。 The main problem is that GetCompetetionStatus is never returning and always timeouts out.
主要问题是GetCompetetionStatus永远不会返回并且总是超时。 I assume I am missing something when creating the handle to monitor, but not sure what.
我假设我在创建要监控的句柄时遗漏了一些东西,但不确定是什么。 This is where I have gotten so far:
这是我到目前为止的地方:
My connect routine: (remove some error handling for clarity ) 我的连接例程:(为清晰起见,删除一些错误处理)
struct sockaddr_in server;
struct hostent *hp;
SOCKET sckfd;
WSADATA wsaData;
int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );
if ((hp = gethostbyname(host)) == NULL)
return NULL;
WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED)
if ((sckfd = WSASocket(AF_INET,SOCK_STREAM,0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET)
{
printf("Error at socket(): Socket\n");
WSACleanup();
return NULL;
}
server.sin_family = AF_INET;
server.sin_port = htons(port);
server.sin_addr = *((struct in_addr *)hp->h_addr);
memset(&(server.sin_zero), 0, 8);
//non zero means non blocking. 0 is blocking.
u_long iMode = -1;
iResult = ioctlsocket(sckfd, FIONBIO, &iMode);
if (iResult != NO_ERROR)
printf("ioctlsocket failed with error: %ld\n", iResult);
HANDLE hNewIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, ulKey, 0);
CreateIoCompletionPort((HANDLE)sckfd, hNewIOCP , ulKey, 0);
connect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr));
//WSAConnect(sckfd, (struct sockaddr *)&server, sizeof(struct sockaddr),NULL,NULL,NULL,NULL);
return sckfd;
Here is the send routine: ( also remove some error handling for clarity ) 这是发送例程:(为清晰起见,还删除了一些错误处理)
IOPortConnect(int ServerSocket,int timeout,string& data){
char buf[BUFSIZE];
strcpy(buf,data.c_str());
WSABUF buffer = { BUFSIZE,buf };
DWORD bytes_recvd;
int r;
ULONG_PTR ulKey = 0;
OVERLAPPED overlapped;
OVERLAPPED* pov = NULL;
HANDLE port;
HANDLE hNewIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, ulKey, 0);
CreateIoCompletionPort((HANDLE)ServerSocket, hNewIOCP , ulKey, 0);
BOOL get = GetQueuedCompletionStatus(hNewIOCP,&bytes_recvd,&ulKey,&pov,timeout*1000);
if(!get)
printf("waiton server failed. Error: %d\n",WSAGetLastError());
if(!pov)
printf("waiton server failed. Error: %d\n",WSAGetLastError());
port = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (u_long)0, 0);
SecureZeroMemory((PVOID) & overlapped, sizeof (WSAOVERLAPPED));
r = WSASend(ServerSocket, &buffer, 1, &bytes_recvd, NULL, &overlapped, NULL);
printf("WSA returned: %d WSALastError: %d\n",r,WSAGetLastError());
if(r != 0)
{
printf("WSASend failed %d\n",GetLastError());
printf("Bytes transfered: %d\n",bytes_recvd);
}
if (WSAGetLastError() == WSA_IO_PENDING)
printf("we are async.\n");
CreateIoCompletionPort(port, &overlapped.hEvent,ulKey, 0);
BOOL test = GetQueuedCompletionStatus(port,&bytes_recvd,&ulKey,&pov,timeout*1000);
CloseHandle(port);
return true;
} }
Any insight would be appreciated. 任何见解将不胜感激。
You are associating the same socket with multiple IOCompletionPorts. 您正在将同一套接字与多个IOCompletionPorts关联。 I'm sure thats not valid.
我相信这无效。 In your IOPortConnect function (Where you do the write) you call CreateIOCompletionPort 4 times passing in one shot handles.
在您的IOPortConnect函数(写入的位置)中,调用CreateIOCompletionPort 4次传递一次性句柄。
My advice: 我的建议:
Note: WSASend returns both 0, and SOCKET_ERROR with WSAGetLastError() as WSA_IO_PENDING as codes to indicate that you will get an IO Completion Packet arriving at GetQueuedCompletionStatus. 注意:WSASend返回0和SOCKET_ERROR,WSAGetLastError()为WSA_IO_PENDING作为代码,表示您将获得到达GetQueuedCompletionStatus的IO完成数据包。 Any other error code means you should process the error immediately as an IO operation was not queued so there will be no further callbacks.
任何其他错误代码意味着您应该立即处理错误,因为IO操作没有排队,因此不会再有回调。
Note2: The OVERLAPPED* passed to the WSASend (or whatever) function is the OVERLAPPED* returned from GetQueuedCompletionStatus. 注意2:传递给WSASend(或其他)函数的OVERLAPPED *是从GetQueuedCompletionStatus返回的OVERLAPPED *。 You can use this fact to pass more context information with the call:
您可以使用此事实通过调用传递更多上下文信息:
struct MYOVERLAPPED {
OVERLAPPED ovl;
};
MYOVERLAPPED ctx;
WSASend(...,&ctx.ovl);
...
OVERLAPPED* pov;
if(GetQueuedCompletionStatus(...,&pov,...)){
MYOVERLAPPED* pCtx = (MYOVERLAPPED*)pov;
Chris has dealt with most of the issues and you've probably already looked at plenty of example code, but... 克里斯已经处理了大部分问题,你可能已经看过很多示例代码,但......
I've got some free IOCP code that's available here: http://www.serverframework.com/products---the-free-framework.html 我有一些免费的IOCP代码可以在这里找到: http : //www.serverframework.com/products---the-free-framework.html
There are also several of my CodeProject articles on the subject linked from that page. 还有一些关于该主题的CodeProject文章与该页面相关联。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.