Click to See Complete Forum and Search --> : Why my server lost data


madhusudankapoor
October 17th, 2005, 01:27 AM
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(0 == OverlapPlus->dwBytes)
continue;

strData = (char*) calloc(OverlapPlus->dwBytes+1,sizeof(char));
strcpy(strData,&OverlapPlus->wbuf.buf[0]);

appendLog(strData);
memset(&OverlapPlus->Overlapped, 0, sizeof(OVERLAPPED));

free(strData);

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

typedef struct _OVERLAPPEDPLUS
{
OVERLAPPED Overlapped;
SOCKET sServer,sClient;
int nOperationCode;
WSABUF wbuf;
char* Buffer;
DWORD dwBytes,dwFlags;
SOCKADDR_STORAGE ClientAddr;
int nClientNumber;
}OVERLAPPEDPLUS, * LP_OVERLAP_PLUS;



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.

DWORD WINAPI ServerWorkerProc(LPVOID lp)
{
HANDLE CompletionPort = (HANDLE)lp;
PER_IO_DATA *PerIoData=NULL;
OVERLAPPED *lpOverlapped=NULL;
LPPER_HANDLE_DATA PerHandleData=NULL;

PerIoData=(LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
DWORD BytesTransferred;
WSABUF wsb;
DWORD Flags=0,bytes;
UINT Ret;
while(TRUE)
{
Ret=GetQueuedCompletionStatus(CompletionPort,
&BytesTransferred,(LPDWORD)&PerHandleData,
&lpOverlapped, INFINITE);
PerIoData = CONTAINING_RECORD(lpOverlapped, PER_IO_DATA,Overlapped);

if (BytesTransferred == 0 &&
(PerIoData->OperationType == RECV_POSTED ||
PerIoData->OperationType == SEND_POSTED))
{
closesocket(PerHandleData->Socket);
continue;

}
else if (PerIoData->OperationType == RECV_POSTED)
{
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);
MessageBox(hMainWnd,data.c_str(),"DataReceived",MB_OK);


}
else if (PerIoData->OperationType == SEND_POSTED)
{

// Write code for dealing send operations

}

}
return 0;
}

madhusudankapoor
October 17th, 2005, 07:56 AM
Thanks!