News: Help with WSock2 & Event objects
From Web (01.07.1997)
Question
From dschwamm@www.henrys.de Tue Jul 01 18:07:21 1997
Path: inf2hro!fu-berlin.de!nntprelay.mathworks.com!howland.erols.net!
ais.net!newsfeed.direct.ca!news.he.net!news.pagesat.net!skypoint.com!
not-for-mail
From: "T. Barlow" <tbarlow@skypoint.com>
Newsgroups: comp.os.ms-windows.programmer.tools.winsock,
comp.os.ms-windows.programmer.networks,comp.os.ms-windows.programmer.win32
Subject: Help with WSock2 & Event objects
Date: Fri, 27 Jun 1997 22:13:52 -0500
Organization: SkyPoint Communications, Inc.
Lines: 124
Message-ID: <33B4816F.C0F20FA6@skypoint.com>
NNTP-Posting-Host: dial067.skypoint.net
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: Mozilla 4.0b5 [en] (Win95; I)
X-Priority: 3 (Normal)
Xref: inf2hro comp.os.ms-windows.programmer.tools.winsock:6954
comp.os.ms-windows.programmer.networks:10124
comp.os.ms-windows.programmer.win32:68800
HI,
I'm working on a MUD server and started looking into
using event objects along with a worker thread to manage
both the listening and connected sockets.
The code is for WSock2, and I'm having a problem.
I'm able to connect a few times, but once I close all
connections via telnet, the code breaks on my DebugBreak()
line in the server thread. I get an error 6 (invalid
handle), but only after I get all the FD_CLOSE signals
and have no sockets left but the listener. BTW, I'm
connecting with telnet using "localhost" (127.0.0.1).
Anyone have a clue what I'm doing wrong? And, is there
a better way to monitor the main socket and all connecting
sockets without polling? It seems like a waste of time
having to call WSAEnumNetworkEvents() for every socket
whenever I get a signal!
Please help.
Here are parts of the code I'm using (no error checks):
// Terminate & socket event handles
ghEvents[EVENT_TERMINATE] = CreateEvent( NULL, TRUE, FALSE, NULL );
ghEvents[EVENT_SERVER] = (HANDLE)WSACreateEvent();
WSAStartup( MAKEWORD( 2, 0 ), &m_wsaData );
gdcMaster = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_IP,NULL,0,0);
bOption = TRUE;
setsockopt(gdcMaster, SOL_SOCKET, SO_DONTLINGER, &bOption,
sizeof(bOption));
sa.sin_family = AF_INET;
sa.sin_port = htons(4242);
sa.sin_addr.s_addr = htonl(INADDR_ANY);
bind(gdcMaster, &sa, sizeof(sa));
WSAEventSelect(gdcMaster,ghEvents[1],FD_ACCEPT|FD_READ|FD_WRITE|FD_CLOSE);
listen(gdcMaster, 5);
ghServerThread = _beginthreadex(
NULL,0,ServerThread,ghEvents,0,&guiThreadID
);
// Here is the cut down thread code .....
unsigned int __stdcall ServerThread( void *pvContext )
{
HANDLE *phEvents = (HANDLE *)pvContext;
WSANETWORKEVENTS EventInfo;
DWORD dwSignal;
while ( 1 )
{
dwSignal = WaitForMultipleObjects(
NUM_EVENTS,phEvents,FALSE,INFINITE
);
if ( dwSignal - WAIT_OBJECT_0 == EVENT_TERMINATE )
return 0;
if ( dwSignal == WAIT_FAILED )
{
DWORD dwErr = GetLastError();
DebugBreak();
}
if ( dwSignal - WAIT_OBJECT_0 == EVENT_SERVER )
{
DESCRIPTOR *pPrev = NULL, *pDel, *p = gpdcConnections;
// Check listener...
WSAEnumNetworkEvents(gdcMaster,NULL,&EventInfo);
if ( EventInfo.lNetworkEvents & FD_ACCEPT )
{
DESCRIPTOR *pNew = (DESCRIPTOR *)calloc(1,sizeof(DESCRIPTOR));
struct sockaddr addr;
int len = sizeof(addr);
pNew->dc = accept(gdcMaster,&addr,&len);
if ( !gpdcConnections )
gpdcConnections = pNew;
else
{
DESCRIPTOR *p = gpdcConnections;
while ( p->pNext ) p = p->pNext;
p->pNext = pNew;
}
giNumConnections++;
ResetEvent(phEvents[EVENT_SERVER]);
continue;
}
// Check all connections
while ( p )
{
WSAEnumNetworkEvents(p->dc,NULL,&EventInfo);
if ( EventInfo.lNetworkEvents & FD_CLOSE )
{
pDel = p;
p = p->pNext;
closesocket(pDel->dc);
free( pDel );
if ( pPrev )
pPrev->pNext = p;
else
gpdcConnections = p;
giNumConnections--;
}
else
{
// Read data...
if ( EventInfo.lNetworkEvents & FD_READ )
recv(p->dc,....) etc...
// Write possible...
if ( EventInfo.lNetworkEvents & FD_WRITE )
write queued data....
pPrev = p;
p = p->pNext;
}
}
ResetEvent(phEvents[EVENT_SERVER]);
}
}
return 0;
}