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:
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.
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
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
}
........
}
}
}
}
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 .
*****************************************************************
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
}
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
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.