I am programming windows socket using IO completion port strategy. I have problem about WSARecv() in IO completion port , the second parameter of WSABUF, if my buffer length is less than the actual message size how can get the rest of the data ? When I called the WSARec() once again, I get the received bytes return by GetQueuedComple tionStatus as zero. Thanks.
WSARecv() WSABUF less than the actual message
Collapse
X
-
Tags: None
-
I read that the first argument is an array of WSABUF structures and the second argument is the number of elements in that array.
The WSABUF struct has a pointer to an array and an unsigned int for the length of the array. Apparantly, you can pre-allocate a bunch of buffers and put the addresses of those buffers and their lengths into the array of WSABUF used as the first argument.
I presume you will need to pre-allocate sufficient memory.
WSARecv . -
Thanks for the prompt reply.
The size or length of the data that I want to receive is UNKNOWN, it is a client requesting for website from the web server. So if I pre-allocate the WSABUF as big as possible, there might be circumstances that will exceed this value. So that's why I need ways to detect the specified WSABUF is less than the actual message that I am receiving from the server. If I have received a portion of message, how can I receive the rest of the message ?
You can see my workerThread of the IOCP.
I have already check the return value of GetQueuedCompke tionStatus, even if my WSABUF length used is less than the actual message when I called WSARecv(), the return value of GetQueuedCompke tionStatus is NON-ZERO. This is my workerThread for IOCP, in case you want to view it. Thanks .
Code:DWORD WINAPI workerThread(LPVOID lParam) { DWORD dwBytesTransfered = 0, recvByte = 0, flags = 0, sentByte = 0; void *lpContext = NULL; OVERLAPPED *pOverlapped = NULL; LPPER_HANDLE_DATA lpHandleData = NULL; int nResult; WSABUF wsaBuf; char buffer[MAX_BUFFER_LEN]; wsaBuf.len = MAX_BUFFER_LEN; wsaBuf.buf = buffer; while(1) { //printf("DEBUG %d\n", GetLastError()); nResult = GetQueuedCompletionStatus(g_hCompletionPort, &dwBytesTransfered,(LPDWORD)&lpContext, &pOverlapped, INFINITE); lpHandleData = (LPPER_HANDLE_DATA) lpContext; if(nResult == FALSE || ((nResult == TRUE) && (dwBytesTransfered == 0))) { printf("GetQueuedCompletionStatus ERROR : %d\n", GetLastError()); if(GetLastError() != 0) // application has completed successfully continue; } printf("Bytes transfered/received : %d\n", dwBytesTransfered); switch(lpHandleData->opCode) { case OP_READ: memset(buffer, 0, MAX_BUFFER_LEN); wsaBuf.buf = buffer; wsaBuf.len = MAX_BUFFER_LEN; if(WSARecv(lpHandleData->serverSocket, &wsaBuf, 1, &recvByte, &flags, &lpHandleData->ol, NULL) == SOCKET_ERROR) if(WSAGetLastError() == WSA_IO_PENDING) printf("WSARecv WSA_IO_PENDING\n"); else printf("WSARecv ERROR : %d\n", WSAGetLastError()); lpHandleData->opCode = OP_WRITE; break; case OP_WRITE: printf("flags : %d\n", flags); printf("Data received : \n%s\n", wsaBuf.buf); break; case OP_CONNECT: // just connected to the server printf("Connected\n"); //printf("DEBUG %d\n", GetLastError()); //memset(&wsaBuf, 0, sizeof(wsaBuf)); memset(buffer, 0, sizeof(buffer)); memset(&lpHandleData->ol, 0, sizeof(lpHandleData->ol)); //\r\nConnection: close sprintf(buffer, "GET / HTTP/1.1\r\nConnection: close\r\nHost: %s\r\n\r\n", lpHandleData->host); wsaBuf.buf = buffer; wsaBuf.len = strlen(buffer); lpHandleData->opCode = OP_READ; if(WSASend(lpHandleData->serverSocket, &wsaBuf, 1, &sentByte, flags, &lpHandleData->ol, FALSE) == SOCKET_ERROR) { if(WSAGetLastError() == WSA_IO_PENDING) printf("WSASend WSA_IO_PENDING\n"); else printf("WSASend ERROR : %d\n", WSAGetLastError()); } else printf("WSASend complete immediately.\n"); break; } } return 0; }
Comment
-
If WSARecv() returns with WSAEMSGSIZE you did not get all of the message. If your WSARecv() call has the MSG_PARTIAL flag set, and your provider supports MSG_PARTIAL, then you can retreive the rest of the message on subsequent WSARecv() calls.
Currently, you have no flags set.Comment
-
Thanks, now I am clear about MSG_PARTIAL, it's only used for UDP socket only. while I am using TCP stream socket.Comment
-
Comment