Click to See Complete Forum and Search --> : WSAEnumNetworkEvents


connie_fox
July 5th, 2004, 03:39 AM
Hi,


Could anyone tell me how to use WSAEnumNetworkEvents? My program is a TCP server, I hope to be notified when the tcp client closes, so that I could close that connection ASAP.


Many thanks.


connie

Naumaan
July 5th, 2004, 07:20 AM
// WSAEnumNetworkEvents copy the actual event into WSANETWORKEVENTS structure this function receive a socket and its associated event as parameter
WSAEnumNetworkEvents(ptrSock->SocketArray[Index],ptrSock->EventArray[Index],&NetworkEvents);

if(NetworkEvents.lNetworkEvents==FD_ACCEPT)
// if WSANETWORKEVENTS structure's INetworkEvents equals to FD_ACCEPT then it means new socket connection request arrive
{
// The iErrorCode parameter is an array of error codes
// associated with the events in lNetworkEvents. For each
// network event type, there is a special event index
// similar to the event type names "except for an additional
// _BIT" string appended to the event name. For example,
// for the FD_READ event type, the index identifier for
// the iErrorCode array is named FD_READ_BIT.
// for the FD_ACCEPT event type, the index identifier for
// the iErrorCode array is named FD_ACCEPT_BIT.

if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
{
break;
}
// If no error occor then
// On FD_ACCEPT event we create a new client socket and pass
// it in accept function.
Ptrnewsock->S=accept(ptrSock->SocketArray[Index],NULL,NULL);
}
else if(NetworkEvents.lNetworkEvents==FD_READ)
// if WSANETWORKEVENTS structure's INetworkEvents equals to
//FD_READ
// then it means Data is available for read
{
if(NetworkEvents.iErrorCode[FD_READ_BIT]!=0)
// checking for any error
{ break;
}
ptrSock->Recv((LPVOID)&ptrSock->SocketArray[Index]);
// If no error occor then calling Recv function for receiving actual data and further processing
}



In FD_CLOSE event you should close that socket

connie_fox
July 16th, 2004, 03:26 AM
Thank you very much for your kind reply and sorry for the delay (I was on a business trip).

I tried WSAEnumNetworkEvents, but failed. Because of the .h file. I am using afxsock.h. WSAEnumNetworkEvents requires winsock2.h. Is there any way that I can use with afxsock.h, so that I may not change a lot of my code?

By the way, is there any better way than WSAEnumNetworkEvents to detect the connection was reset by the remote side?



connie

connie_fox
July 16th, 2004, 04:16 AM
Hi,

I changed to use "winsock2.h", the program can run.

But I still can not detect tcp client's disconnect. My program is a TCP server. Where should I put WSAEnumNetworkEvents()? Should I use OnTimer()?


Thanks.

connie

Naumaan
July 16th, 2004, 04:50 AM
Use the following code to detect closing of a socket

else if(NetworkEvents.lNetworkEvents==FD_CLOSE) // if WSANETWORKEVENTS structure's INetworkEvents equals to FD_CLOSE
// then it means Socket is closed
{
if(NetworkEvents.iErrorCode[FD_CLOSE_BIT]!=0 ) // checking for any error
{
break;
}
closesocket(ptrSock->SocketArray[Index]);
// if no error occor then closing the socket
// Index variable contain the index of socket and event objects
WSACloseEvent(ptrSock->EventArray[Index]); // Closing the event object

}

u did not require any timer because when u r waiting for multiple events, this close event will also handled in that thread.

I think u r using WSAEventSelect model of socket so u have only this choice to detect socket events.

connie_fox
July 18th, 2004, 08:31 PM
Hi,

Thanks for your reply.

I used select ( 0, &fdset, NULL, NULL, &timeout ) in SocketCheck() to detect client's connection. My code is like this:

while(b_ServerStop!=true)
{
WSAEnumNetworkEvents(client,myevent,&NetworkEvents);

if(NetworkEvents.lNetworkEvents==FD_CLOSE)
{
closesocket(client);
}

if (pdlg_sevr->SocketCheck(server,SC_READ))
{
client=accept(server,
(struct sockaddr*)&from,&fromlen);
...............
}
}

I can not detect client's disconnection.

Could you please give me some advice?


connie

Naumaan
July 18th, 2004, 11:50 PM
can u explain which socket model u r using
Try to use like this

if(NetworkEvents.lNetworkEvents==FD_ACCEPT)
{
if (pdlg_sevr->SocketCheck(server,SC_READ))
{
client=accept(server,
(struct sockaddr*)&from,&fromlen);
...............
// After acceptance of socket call WSAEventSelect function on newly
//accepted socket.
WSAEventSelect(client,newevent,FD_READ | FD_WRITE | FD_CLOSE);
// Here newevent is a newly created event by WSACreateEvent() function
// I m using WSAEventSelect Model
}

}

connie_fox
July 19th, 2004, 03:43 AM
Hi,

Thank you.

I changed my code according to your code. But it still does not work. :(

I used
SOCKET client, server;
select();

not WSAEVENTSELECT(). Actually I can not detect connection event with WSAEVENTSELECT(). How is that? Is that I need to include some other .h file?


connie

Naumaan
July 19th, 2004, 04:51 AM
Paste your Listen , Accept and Connect code then i can give u proper solution.

because WSAEnumNetworkEvent function is used to handle WSAEventSelect Model Properly.
So if u r using select function then it did not take Event object so attach your code in reply.

connie_fox
July 19th, 2004, 07:49 PM
Hi,

Thanks for your kind help.

my code is:

WSADATA wsaData;
sockaddr_in local;
int wsaret=WSAStartup(0x101,&wsaData);
if(wsaret!=0)
{
return -1;
}
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons((u_short)sevr_port);
server=socket(AF_INET,SOCK_STREAM,0);
if(server==INVALID_SOCKET)
{
WSACleanup ( );
AfxMessageBox("Create Server socket failed!");
return -1;
}
if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
{
closesocket ( server );
WSACleanup ( );
AfxMessageBox("Server socket bind failed!");
return -1;
}
if(listen(server, ACCEPT_QUEUE)!=0)
{
closesocket ( server );
WSACleanup ( );
AfxMessageBox("Server socket listen failed!");
return -1;
}

SOCKET client;
sockaddr_in from;
int fromlen=sizeof(from);
WSAEVENT myevent,newevent;
WSANETWORKEVENTS NetworkEvents;

while(b_ServerStop!=true)
{
WSAEnumNetworkEvents(client,myevent,&NetworkEvents);
WSAEventSelect(client,newevent,FD_READ | FD_WRITE | FD_CLOSE);

if(NetworkEvents.lNetworkEvents==FD_ACCEPT)
{

if (pdlg_sevr->SocketCheck(server,SC_READ))
{
client=accept(server,
(struct sockaddr*)&from,&fromlen);
........
}
}
}


connie

Naumaan
July 19th, 2004, 11:56 PM
Try to use ur code like this
--------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------
WSAEVENT EventArray[64];
SOCKET SockArray[64];
UINT EventTotal=0;
WSADATA wsaData;
sockaddr_in local;
int wsaret=WSAStartup(MAKEWORD(2,2),&WsaData);
if(wsaret!=0)
{
return -1;
}
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons((u_short)sevr_port);
server=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(server==INVALID_SOCKET)
{
WSACleanup ( );
AfxMessageBox("Create Server socket failed!");
return -1;
}
if(bind(server,(sockaddr*)&local,sizeof(local))!=0)
{
closesocket ( server );
WSACleanup ( );
AfxMessageBox("Server socket bind failed!");
return -1;
}

//****************************************************************
WSAEVENT newserverevent; // Event object to attach with listening socket
if((newserverevent=WSACreateEvent())==WSA_INVALID_EVENT) // Create a new
// event object and assign to newevent
return -1; // if event cannot created then return -1
if(WSAEventSelect(server,newserverevent,FD_ACCEPT | FD_CLOSE)
==SOCKET_ERROR)
// Calling WSAEventSelect function on
// Listening socket and newevent to attach
// Accept and close events
return -1; // If function failes then return -1

EventArray[EventTotal]=newserverevent;
SockArray[EventTotal]=server;
EventTotal++;
//***************************************************************

if(listen(server, ACCEPT_QUEUE)!=0)
{
closesocket ( server );
WSACleanup ( );
AfxMessageBox("Server socket listen failed!");
return -1;
}

//***************************************************************
//***************************************************************

SOCKET client;


WSANETWORKEVENTS NetworkEvents;
UINT Index,ret;
while(b_ServerStop!=true)
{

ret=WSAWaitForMultipleEvents(EventsTotal,EventArray,FALSE,
WSA_INFINITE,FALSE);
if ((ret != WSA_WAIT_FAILED) && (ret != WSA_WAIT_TIMEOUT))
{
Index=ret-WSA_WAIT_EVENT_0;
for(int i=Index;i<EventsTotal;i++)
{

Index=WSAWaitForMultipleEvents(1,&EventArray[i],TRUE,1000,FALSE);
if ((Index != WSA_WAIT_FAILED) && (Index != WSA_WAIT_TIMEOUT))
{
Index=i;
WSAEnumNetworkEvents(SocketArray[Index],EventArray[Index]
,&NetworkEvents);
if(NetworkEvents.lNetworkEvents==FD_ACCEPT)
{
if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
{
break;
}
// If no error occor then
// On FD_ACCEPT event we create a new client socket and
// pass it in accept function.
// Accept function extract that newly connected socket from que
// after accept function we call WSAEventSelect on
// newly accepted socket
// to get its events in this while loop
WSAEVENT newclientevent; // Creating a new WSAEVENT object
newclientevent=WSACreateEvent();
client=accept(SocketArray[Index],NULL,NULL);
// CAlling WSAEventSelect function on newly accepted socket to
// receive its READ,WRITE AND CLOSE Events in this thread
WSAEventSelect(client,neweclientvent,FD_READ | FD_WRITE |
FD_CLOSE);
// FD_ACCEPT event occors only on server end so i m inserting newly
// accepted socket and its evnet into listening socket's event and
// socket arrays
// Inserting new socket into socket arrray
SocketArray[EventsTotal]=client;
EventArray[EventsTotal]=newclientevent; // Inserting new event
//associated with new socket
// into event array
EventsTotal++; // Increasing the EventTotal variable
}
else if(NetworkEvents.lNetworkEvents==FD_READ)
{
// YOUR socket data read code
}
else if(NetworkEvents.lNetworkEvents==FD_CLOSE)
{
// YOUR socket close code
}
........
}
}
}
}


--------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------

connie_fox
July 20th, 2004, 01:30 AM
Hi,

Thanks for your great help!

I tried. FD_ACCEPT works well. But FD_CLOSE does not. I have a simple VB program acts as TCP client, when I close that program, the TCP server in VC receives an event, but the NetworkEvents.INetworkEvents=0, so it can not close the socket. I noticed that FD_ACCEPT means NetworkEvents.INetworkEvents=8.
I guess for FD_CLOSE, NetworkEvents.INetworkEvents=32.

I wonder why NetworkEvents.INetworkEvents value is incorrect when the tcp client quit?

connie

Naumaan
July 20th, 2004, 01:51 AM
Have u tried the Accept portion just like my code

there are few steps.

1: Create a new WSAEVEVENT
WSAEVENT newclientevent; // Creating a new WSAEVENT object
newclientevent=WSACreateEvent();

2: Call Accept function and assign newly accepted socket to your client socket
SOCKET client=accept(serversock,NULL,NULL);

3: attaching the newclientevent with newly accepted socket for receiving its events
WSAEventSelect(client,neweclientvent,FD_READ | FD_WRITE |
FD_CLOSE);

4: inserting the newly accepted socket into socket array and inserting newclientevent into Event array and increase EventTotal variable
if u did not do the forth step then u cannot provide service to newly accepted socket .

SocketArray[EventsTotal]=client;
EventArray[EventsTotal]=newclientevent;
EventTotal++;









*****************************************************************
if(NetworkEvents.lNetworkEvents==FD_ACCEPT)
{
if(NetworkEvents.iErrorCode[FD_ACCEPT_BIT]!=0)
{
break;
}
// If no error occor then
// On FD_ACCEPT event we create a new client socket and
// pass it in accept function.
// Accept function extract that newly connected socket from que
// after accept function we call WSAEventSelect on
// newly accepted socket
// to get its events in this while loop
WSAEVENT newclientevent; // Creating a new WSAEVENT object
newclientevent=WSACreateEvent();
client=accept(SocketArray[Index],NULL,NULL);
// CAlling WSAEventSelect function on newly accepted socket to
// receive its READ,WRITE AND CLOSE Events in this thread
WSAEventSelect(client,neweclientvent,FD_READ | FD_WRITE |
FD_CLOSE);
// FD_ACCEPT event occors only on server end so i m inserting newly
// accepted socket and its evnet into listening socket's event and
// socket arrays
// Inserting new socket into socket arrray
SocketArray[EventsTotal]=client;
EventArray[EventsTotal]=newclientevent; // Inserting new event
//associated with new socket
// into event array
EventsTotal++; // Increasing the EventTotal variable
}

*****************************************************************

connie_fox
December 2nd, 2004, 12:13 AM
Hello,

I tested again and found that while(b_ServerStop!=true)
{
......
}

in my TCP server application sometimes goes into infinite loop.

I tested with my code and a sample VC++ TCP client application. I kept my TCP server application running. The client would do connect(), send(), shutdown(), step by step, then I closes this client application. Then I restarted it.

I found that my application worked well for the first time the client connected,but when the client connected for the second time,my application continuously receive network event after client connect(),NetworkEvents.lNetworkEvents=8, then goes into infinite loop.

How is that? Could you please give me a piece of advice?

Thanks and best regards,
connie