Tengo problemas para implementar el cliente TCP IOCP. Implementé kqueue en Mac OSX, por lo que estaba buscando hacer algo similar en Windows y tengo entendido que IOCP es lo más parecido. El principal problema es que GetCompetetionStatus nunca regresa y siempre expira. Supongo que me falta algo cuando creo el controlador para monitorear, pero no estoy seguro de qué. Aquí es donde he conseguido hasta ahora:Cliente IOCP C++ TCP
Mi rutina de conexión: (eliminar algunos gastos de envío para mayor claridad de error)
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;
Aquí es la rutina de envío: (también eliminar algunos gastos de envío para mayor claridad de error)
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;
}
Cualquier penetración sería apreciada.
¿Realmente verifica el valor de retorno de 'CreateIoCompletionPort'? –
poniendo GetLastError después de que el CreateIoCompletionPort en cada función devuelve un error 87 (parámetro incorrecto) y error 6 (identificador no válido). No estoy seguro de por qué están regresando incorrectos ya que ambos son identificadores válidos (ServerSocket y puerto). – daltoniam