Can you pls help me why I my server lost data , What should i do in case of Error
Here is my server Code
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
/*-- Notify Starting of server -- */
printf("\nHello Server Started, I am in worker thread! \n");
HANDLE hIocp = (HANDLE) CompletionPortID;
ULONG_PTR *PerHandleKey;
OVERLAPPED *Overlap;
OVERLAPPEDPLUS *OverlapPlus,*newolp;
DWORD dwBytesXfered;
int ret;
char *strData ;
while (1)
{
ret = GetQueuedCompletionStatus(hIocp,&dwBytesXfered,(PULONG_PTR)&PerHandleKey,&Overlap,INFINITE);
if (ret == 0){
continue;
}
OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, Overlapped);
/*--- Process Data According to Operation Code ---*/
switch (OverlapPlus->nOperationCode )
{
case OP_READ:
// Process the data read Repost the read if necessary, reusing the same receive buffer as before
ZeroMemory(&(OverlapPlus->Overlapped),sizeof(OVERLAPPED));
ret = WSARecv(OverlapPlus->sClient,&OverlapPlus->wbuf,1,&OverlapPlus->dwBytes,&OverlapPlus->dwFlags,&OverlapPlus->Overlapped, NULL);
if (ret == SOCKET_ERROR)
{
ret = WSAGetLastError();
if ( ret != WSA_IO_PENDING)
{
// What should i do in case of Error???
printf("Error occur at WSARecv() : %d", ret);
break;
}
}
break;
case OP_WRITE:
appendLog("WRITE");
// Process the data sent, etc.
break;//…
}
}
}
Naumaan
October 17th, 2005, 02:09 AM
Actually In IOCP Model when u call GetQueuedCompletionStatus function it attempts to dequeue an I/O completion packet from a specified input/output completion port. So in ur code it seems u r copying data after calling WSARecv, U have to copy received buffer first and then call WSARecv to further post ur buffers to receive data.
madhusudankapoor
October 17th, 2005, 02:42 AM
Thanks!
I change my code but it gives Null Reference exception Why???
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
/*-- Notify Starting of server -- */
printf("\nHello Server Started, I am in worker thread! \n");
HANDLE hIocp = (HANDLE) CompletionPortID;
ULONG_PTR *PerHandleKey;
OVERLAPPED *Overlap;
OVERLAPPEDPLUS *OverlapPlus,*newolp;
DWORD dwBytesXfered;
int ret;
char *strData ;
g_pLoggerClientGeneral = new LoggerClient();
while (1)
{
ret = GetQueuedCompletionStatus(hIocp,&dwBytesXfered,(PULONG_PTR)&PerHandleKey,&Overlap,INFINITE);
if (ret == 0){
continue;
}
OverlapPlus = CONTAINING_RECORD(Overlap, OVERLAPPEDPLUS, Overlapped);
/*--- Process Data According to Operation Code ---*/
switch (OverlapPlus->nOperationCode )
{
case OP_READ:
// Process the data read Repost the read if necessary, reusing the same receive buffer as before
strData = (char*) calloc(OverlapPlus->dwBytes+1,sizeof(char));
strcpy(strData,&OverlapPlus->wbuf.buf[0]);
appendLog(strData);
printf("\nBytes:\t%d\nMessage:\t%s",OverlapPlus->dwBytes,strData);
free(strData);
memset(&OverlapPlus->Overlapped, 0, sizeof(OVERLAPPED));
ret = WSARecv(OverlapPlus->sClient,&OverlapPlus->wbuf,1,&OverlapPlus->dwBytes,&OverlapPlus->dwFlags,&OverlapPlus->Overlapped, NULL);
if(0 == OverlapPlus->dwBytes)
continue;
if (ret == SOCKET_ERROR)
{
ret = WSAGetLastError();
if ( ret != WSA_IO_PENDING)
{
printf("Error occur at WSARecv() : %d", ret);
break;
}
}
break;
case OP_WRITE:
appendLog("WRITE");
// Process the data sent, etc.
break;//…
}
}
}
Naumaan
October 17th, 2005, 03:55 AM
Try to use like following code , Actually dwBytesXfered contain number of received bytes after GetQueuedCompletionStatus function. so Use such variable to allocate memory.
case OP_READ:
// Process the data read Repost the read if necessary, reusing the same receive buffer as before
strData = (char*) malloc(dwBytesXfered); // Size of received bytes in dwBytesXfered
strcpy(strData,&OverlapPlus->wbuf.buf);
appendLog(strData);
printf("\nBytes:\t%d\nMessage:\t%s",OverlapPlus->dwBytes,strData);
free(strData);
memset(&OverlapPlus->Overlapped, 0, sizeof(OVERLAPPED));
ZeroMemory(&OverlapPlus->wbuf.buf,sizeof(OverlapPlus->wbuf.buf));
ret = WSARecv(OverlapPlus->sClient,&OverlapPlus->wbuf,1,&OverlapPlus->dwBytes,&OverlapPlus->dwFlags,&OverlapPlus->Overlapped, NULL);
It may contain some errors due to modificatios.
The following piece of code can helps u,its for testing only and related to Receiving data.
else if (PerIoData->OperationType == RECV_POSTED)
{
WSABUF wsb;
ZeroMemory(&PerIoData->Overlapped,sizeof(PerIoData->Overlapped));
string data=">";
data+=PerIoData->Buffer;
wsb.buf=PerIoData->Buffer;
wsb.len=DATA_BUFSIZE; //1024
PerIoData->OperationType=RECV_POSTED;
ZeroMemory(&PerIoData->Buffer,sizeof(PerIoData->Buffer));
WSARecv(PerHandleData->Socket,&wsb,1,&bytes,&Flags,&PerIoData->Overlapped,NULL);
// Now data string contain received data.
}
madhusudankapoor
October 17th, 2005, 04:28 AM
I did coke as u said but there is NULL Exception Error WHY
Even my OverlapPlus struct did not contain Buffer, But insert still it gives Error, my overlapPlus structure is
Code Sample is ...................................
case OP_READ:
WSABUF wsb;
DWORD dwBytes,dwFlags;
ZeroMemory(&OverlapPlus->Overlapped,sizeof(OverlapPlus->Overlapped));
data = ">";//
data += OverlapPlus->Buffer;
wsb.buf = OverlapPlus->Buffer;
wsb.len = DATA_BUFSIZE; //1024
OverlapPlus->nOperationCode = OP_READ;
ZeroMemory(&OverlapPlus->Buffer,sizeof(OverlapPlus->Buffer));
printf("%s",data);
WSARecv(OverlapPlus->sClient,&wsb,1,&dwBytes,&dwFlags,&OverlapPlus->Overlapped,NULL);
printf("%s",data);
break;
Can u send me a sample of server using IOCP. All ther program available on internet is too difficult and tooooo long to understan. Pls help me
Regrds
Madhu S. Kapoor
madhusudankapoor
October 17th, 2005, 04:32 AM
In ur code you take two types of structue
PreIOData and PreHandleData
But i take only one structure..
Pls explain me funda of these two Structure
Naumaan
October 17th, 2005, 05:28 AM
I m using following two structures
typedef struct _PER_HANDLE_DATA
{
SOCKET Socket;
SOCKADDR_IN ClientAddr;
// Other information useful to be associated with the handle
UINT ID;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;
typedef struct _PER_IO_DATA
{
OVERLAPPED Overlapped;
char Buffer[DATA_BUFSIZE];
int BufferLen;
int OperationType;
} PER_IO_DATA, * LPPER_IO_DATA;
Actually When we start an operation just like sending or receiving we need some buffer to post, so through out the program we need saveral buffers may be simultaniously for each socket. So we preffer to make two structures one is PER_IO_DATA and other is PER_HANDLE_DATA .
PER_IO_DATA as its name describe (PER IO = For Each IO ). for each IO we need one PER_IO_DATA object. And PER_HANDLE_DATA contain socket and all the information associated with that socket, and it remains same through out the socket life.
Here is the code for Completion thread with above two structures, it may helps u . Its just for testing purpose.