Difference between revisions of "Server.c"

From Organic Design wiki
m
m
 
(53 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
{{legacy}}
 +
<source lang="c">
 
// This article and all its includes are licenced under LGPL
 
// This article and all its includes are licenced under LGPL
 
// GPL: http://www.gnu.org/copyleft/lesser.html
 
// GPL: http://www.gnu.org/copyleft/lesser.html
 
// SRC: http://www.organicdesign.co.nz/server.c
 
// SRC: http://www.organicdesign.co.nz/server.c
 
  
 
#define svrDELAY 0        // normal operation is 0 for no delay
 
#define svrDELAY 0        // normal operation is 0 for no delay
#define svrPAKSIZE 0x10    // keep packet-size small for non-multithreaded design
+
#define svrPAKSIZE 128    // keep packet-size small for non-multithreaded design
#define svrBUFSIZE 0x80   // dictates max message size
+
#define svrPAKMAX  16384  // maximum packet size to allow for variable pak size at runtime
 +
#define svrBUFSIZE 4096   // dictates max message size
 
#define svrMAXCLIENTS 1000 // used by listen()
 
#define svrMAXCLIENTS 1000 // used by listen()
 
#ifndef __WIN32__
 
#ifndef __WIN32__
Line 12: Line 14:
 
#endif
 
#endif
  
// Socket structures and variables
+
// Socket structures, globals and prototypes
 +
void server();
 +
int serverInit();
 +
int serverExit();
 +
int nonblocking(int socket);
 +
fd_set *fdsetInit(int fd);
 +
fd_set fdset;
 +
int sock,fd;
 
struct sockaddr_in addr;
 
struct sockaddr_in addr;
 
struct timeval to;
 
struct timeval to;
fd_set fdset;
 
 
unsigned long int sockopt_on;
 
unsigned long int sockopt_on;
int sock;
 
  
// Stream info structure and globals
+
// Client/Stream info structure, globals and prototypes
const char *iTerm = "\r\n\r\n";
 
 
char *pBuf;                // Buffer to read/write data packets
 
char *pBuf;                // Buffer to read/write data packets
 +
const char *term = "\r\n\r\n";
 
typedef struct siStruct {
 
typedef struct siStruct {
int fd;           // File-descriptor for this stream
+
int fd;               // File-descriptor for this stream
char *iBuf, *oBuf; // Message buffers for this stream
+
char *iBuf, *oBuf;     // Message buffers for this stream
iPtr;              // Index into input-buffer for next packet to start at
+
int iPtr;              // Index into input-buffer for next packet to start at
tPtr;              // Index into iTerm (atomised strcmp incase terminator spans packet-boundary)
+
int tPtr;              // Index into term (atomised strcmp incase terminator spans packet-boundary)
oPtr;
+
int oPtr;
 
} streamInfo;
 
} streamInfo;
 
+
void client();
// Function prototypes
+
int streamOpen(int fd,char *resource);
//void server(); // declared earlier in nodalHusk since called in root loop
+
void streamClose(streamInfo *stream);
//void client();
+
void streamProcess(streamInfo *stream);
void process();
 
int server_init();
 
int server_exit();
 
int nonblocking(int socket);
 
  
  
 
// Initialise socket listening on specified port
 
// Initialise socket listening on specified port
int server_init() {
+
int serverInit() {
  
 
#if __WIN32__
 
#if __WIN32__
Line 58: Line 61:
 
// Do the usual socket polava: create,options,bind,listen
 
// Do the usual socket polava: create,options,bind,listen
 
if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
 
if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
logErrNum("socket() failed returning %d",WSAGetLastError());
+
logErrNum("init/socket() failed returning %d",WSAGetLastError());
 
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0)
 
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0)
logErr("setsockopt() failed!");
+
logErrNum("init/setsockopt() failed returning %d",WSAGetLastError());
if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0) logErr("bind() failed!");
+
if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0)
if (listen(sock,svrMAXCLIENTS)<0) logErr("listen() failed!");
+
logErrNum("init/bind() failed returning %d",WSAGetLastError());
if (errno == 0) {
+
if (listen(sock,svrMAXCLIENTS)<0)
 +
logErrNum("init/listen() failed returning %d",WSAGetLastError());
 +
 
 +
if (WSAGetLastError() == 0) {
 
char *msg = malloc(100);
 
char *msg = malloc(100);
 
sprintf(msg,"Daemon \"%s\" started successfully and serving on port %d.",peer,port);
 
sprintf(msg,"Daemon \"%s\" started successfully and serving on port %d.",peer,port);
Line 71: Line 77:
 
else {
 
else {
 
logAdd("Server failed to start!");
 
logAdd("Server failed to start!");
return errno;
+
return WSAGetLastError();
 
}
 
}
  
pBuf = malloc(svrPAKSIZE);
+
// Globals for server() and client() quantum-functions
 +
pBuf = malloc(svrPAKMAX);
 +
*nodeState(nodeSERVER,0) = &server;
 +
nodeSetValue(nodeSERVER,nodeCODE,nodeTRUE);
  
 
return 0;
 
return 0;
Line 81: Line 90:
  
 
// Perform any cleanup for socket
 
// Perform any cleanup for socket
int server_exit() {
+
int serverExit() {
 +
free(pBuf);
 
// todo: close streams and free buffers etc
 
// todo: close streams and free buffers etc
 
#if __WIN32__
 
#if __WIN32__
Line 102: Line 112:
  
  
// Function called by each stream-node in network's reduction loop
+
// Return pointer to fdset filled with passed file-descriptor ready for a select() call
// - there is also a streams-container node containing zero or more stream nodes
+
fd_set *fdsetInit(int fd) {
void server() {
 
 
FD_ZERO(&fdset);
 
FD_ZERO(&fdset);
FD_SET(sock,&fdset);
+
FD_SET(fd,&fdset);
 
to.tv_sec = to.tv_usec = svrDELAY;
 
to.tv_sec = to.tv_usec = svrDELAY;
if (select(sock+1,&fdset,NULL,NULL,&to)>0) {
+
return &fdset;
// New connection request, accpet and create new stream-node
+
}
int fd = nonblocking(accept(sock,NULL,NULL));
+
 
if (fd>0) {
+
 
printf("New connection: Stream%d.\n",fd);
+
// Process message in iBuf which should be a complete HTTP GET request
streamInfo *newsi = malloc(sizeof(streamInfo));
+
// - iPtr is put back to 0 so next message fills from start of iBuf
newsi->fd = fd;
+
void streamProcess(streamInfo *stream) {
newsi->iBuf = malloc(svrBUFSIZE);
+
char *rqst, *end, *msg = stream->iBuf;
newsi->oBuf = malloc(svrBUFSIZE);
+
if (strncmp("GET /",msg,5)==0) {
newsi->iPtr = newsi->oPtr = newsi->tPtr = 0;
+
 
node n = nodeGetValue(nodeCLIENTS,nodeLOOP);
+
// Extract request path & query-string
n = nodeLoopInsert(n,nodeNULL);
+
rqst = end = msg+4;
nodeSetValue(nodeCLIENTS,nodeLOOP,n);
+
while(*++end > ' ');
nodeSetValue(n,nodeCODE,nodeTRUE);
+
*end = '\0';
*nodeState(n,nodeNULL) = &client;
+
printf("Request:\"%s\"\n",rqst);
*nodeState(n,nodeSTREAMINFO) = newsi;
+
 
}
+
// Exit if /stop requested
else logErr("accept(): failed!");
+
if (strcmp("/stop",rqst)==0) nodeExit();
 +
 
 +
// Send test response back
 +
send(stream->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nStink eh?",134,0);
 +
}
 +
else {
 +
send(stream->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nNo GET!!!",134,0);
 +
logAdd("Peerd only supports GET requests currently!");
 +
}
 +
stream->iPtr = 0; // reset iPtr ready for next message
 +
}
 +
 
 +
 
 +
// Create new client-node and streamInfo structure from passed file-descriptor
 +
// - if fd is NULL, then try and create one by resolving the resource string
 +
void streamOpen(int fd, char *resource) {
 +
if (fd == NULL) {
 +
// if resource is /^[./]/ then its a file
 +
// - file will have different packet size etc
 +
// - may need to include &recv/&read etc in streamInfo struct
 
}
 
}
 +
if (fd < 0) return logErrMsg("Couldn't open resource \"%s\"",resource);
 +
logAddNum("New connection: Stream%d.",fd);
 +
// Create new streamInfo structure and allocate buffers
 +
streamInfo *stream = malloc(sizeof(streamInfo));
 +
stream->fd = fd;
 +
stream->iBuf = malloc(svrBUFSIZE);
 +
stream->oBuf = malloc(svrBUFSIZE);
 +
stream->iPtr = stream->oPtr = stream->tPtr = 0;
 +
 +
// Create new client-node in clients-loop and add the new streamInfo
 +
node nc = nodeGetValue(nodeCLIENTS,nodeLOOP);
 +
nc = nodeLoopInsert(nc,0);
 +
nodeSetValue(nodeCLIENTS,nodeLOOP,nc);
 +
nodeSetValue(nc,nodeCODE,nodeTRUE);
 +
*nodeState(nc,0) = &client;
 +
*nodeState(nc,nodeSTREAM) = stream;
 +
}
 +
 +
 +
// Close the passed stream, free its resources and remove from clients-loop
 +
void streamClose(streamInfo *stream) {
 +
printf("Stream%d closed.\n",stream->fd);
 +
//nodeLoopRemove(this); // NOTE: reduction not handling PREV
 +
free(stream->iBuf);
 +
free(stream->oBuf);
 +
free(stream);
 
}
 
}
  
Line 132: Line 186:
 
// Each of the stream nodes points to this function in its State
 
// Each of the stream nodes points to this function in its State
 
void client() {
 
void client() {
// Get the info for this stream ready for reading/writing a packet if necessary
+
 
streamInfo *info = *nodeState(this, nodeSTREAMINFO);
+
// Get pointer to the streamInfo structure in current nodal context (this)
char *iBuf = info->iBuf, *oBuf = info->oBuf;
+
streamInfo *stream = *nodeState(this, nodeSTREAM);
int n, i = 0, fd = info->fd;
+
fd = stream->fd;
 +
char *iBuf = stream->iBuf, *oBuf = stream->oBuf;
 +
int n, i = 0;
  
 
// If any data to recieve, read a packet
 
// If any data to recieve, read a packet
FD_ZERO(&fdset);
+
if (select(fd+1,fdsetInit(fd),NULL,NULL,&to)>0) {
FD_SET(fd,&fdset);
 
to.tv_sec = to.tv_usec = svrDELAY;
 
if (select(fd+1,&fdset,NULL,NULL,&to)>0) {
 
 
if ((n = recv(fd,pBuf,svrPAKSIZE,0)) > 0) {
 
if ((n = recv(fd,pBuf,svrPAKSIZE,0)) > 0) {
 
// Some bytes were read, append to current message (loop last packet if msg too big)
 
// Some bytes were read, append to current message (loop last packet if msg too big)
if (info->iPtr > svrBUFSIZE-svrPAKSIZE) info->iPtr -= svrPAKSIZE;
+
if (stream->iPtr > svrBUFSIZE-svrPAKSIZE) stream->iPtr -= svrPAKSIZE;
 
while (n--)  // Append current msg, for each complete msg, process it & reset iPtr
 
while (n--)  // Append current msg, for each complete msg, process it & reset iPtr
if ((iBuf[info->iPtr++] = pBuf[i++]) != iTerm[info->tPtr++]) info->tPtr = 0;
+
if ((iBuf[stream->iPtr++] = pBuf[i++]) != term[stream->tPtr++]) stream->tPtr = 0;
else if (iTerm[info->tPtr] == 0) process(info);
+
else if (term[stream->tPtr] == 0) streamProcess(stream);
 
}
 
}
else if (n == 0) {
+
else if (n == 0) streamClose(stream); // Zero bytes were read, do orderly termination
// Zero bytes were read, do orderly termination
+
else logErrNum("client/recv() failed returning %d",WSAGetLastError());
printf("Stream%d closed.\n",fd);
 
//nodeLoopRemove(this); // NOTE: reduction not handling PREV
 
free(iBuf);
 
free(oBuf);
 
free(info);
 
}
 
else logErrNum("recv() failed returning %d",WSAGetLastError());
 
 
}
 
}
return;
+
 
 
// Data to send?
 
// Data to send?
FD_ZERO(&fdset);
+
//if (select(fd+1,NULL,fdsetInit(fd),NULL,&to)>0) {
FD_SET(fd,&fdset);
 
to.tv_sec = to.tv_usec = svrDELAY;
 
if (select(fd+1,NULL,&fdset,NULL,&to)>0) {
 
 
// write a packet from outbuf
 
// write a packet from outbuf
 
//int len = svrPAKSIZE; // or less
 
//int len = svrPAKSIZE; // or less
 
//if (send(fd,oBuf+oPtr,len,0)<0) logErr("send() failed!");
 
//if (send(fd,oBuf+oPtr,len,0)<0) logErr("send() failed!");
}
+
// }
  
 
}
 
}
  
  
// Process message in iBuf which should be a complete HTTP GET request
+
// Function called by each stream-node in network's reduction loop
// - iPtr is put back to 0 so next message fills from start of iBuf
+
// - Checks if any new connections waiting on listening socket,
void process(streamInfo *info) {
+
//  if so accept and call streamOpen() with new file-descriptor
info->iPtr = 0;
+
void server() {
char *rqst, *end, *msg = info->iBuf;
+
if (select(sock+1,fdsetInit(sock),NULL,NULL,&to)>0)
if (strncmp("GET /",msg,5)==0) {
+
if ((fd = nonblocking(accept(sock,NULL,NULL)))>0) streamOpen(fd,NULL);
 
+
else logErrNum("server/accept() failed returning %d",WSAGetLastError());
// Extract request path & query-string
 
rqst = end = msg+4;
 
while(*++end > ' ');
 
*end = '\0';
 
printf("Request:\"%s\"\n",rqst);
 
 
 
// Exit if /stop requested
 
if (strcmp("/stop",rqst)==0) {
 
logAdd("/stop requested, stopping.");
 
exit(EXIT_SUCCESS);
 
}
 
 
 
// Send test response back
 
send(info->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nStink eh?",134,0);
 
}
 
else {
 
send(info->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nNo GET!!!",134,0);
 
logAdd("Peerd only supports GET requests currently!");
 
}
 
 
}
 
}
 +
</source>
 +
[[Category:C]]

Latest revision as of 15:22, 6 July 2015

Legacy.svg Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, now this page is for historic record only.
// This article and all its includes are licenced under LGPL
// GPL: http://www.gnu.org/copyleft/lesser.html
// SRC: http://www.organicdesign.co.nz/server.c

#define svrDELAY 0         // normal operation is 0 for no delay
#define svrPAKSIZE 128     // keep packet-size small for non-multithreaded design
#define svrPAKMAX  16384   // maximum packet size to allow for variable pak size at runtime
#define svrBUFSIZE 4096    // dictates max message size
#define svrMAXCLIENTS 1000 // used by listen()
#ifndef __WIN32__
#define WSAGetLastError() errno
#endif

// Socket structures, globals and prototypes
void server();
int serverInit();
int serverExit();
int nonblocking(int socket);
fd_set *fdsetInit(int fd);
fd_set fdset;
int sock,fd;
struct sockaddr_in addr;
struct timeval to;
unsigned long int sockopt_on;

// Client/Stream info structure, globals and prototypes
char *pBuf;                // Buffer to read/write data packets
const char *term = "\r\n\r\n";
typedef struct siStruct {
	int fd;                // File-descriptor for this stream
	char *iBuf, *oBuf;     // Message buffers for this stream
	int iPtr;              // Index into input-buffer for next packet to start at
	int tPtr;              // Index into term (atomised strcmp incase terminator spans packet-boundary)
	int oPtr;
	} streamInfo;
void client();
int streamOpen(int fd,char *resource);
void streamClose(streamInfo *stream);
void streamProcess(streamInfo *stream);


// Initialise socket listening on specified port
int serverInit() {

	#if __WIN32__
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,0),&wsaData)!=0) logErr("WSAStartup() failed!");
	#endif

	// Set up structures for socket & select
	sockopt_on = 1;
	int szAddr = sizeof(struct sockaddr_in);
	memset((char*)&addr, 0, szAddr); // zero the struct
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	errno = 0;

	// Do the usual socket polava: create,options,bind,listen
	if ((sock = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)
		logErrNum("init/socket() failed returning %d",WSAGetLastError());
	if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char*)&sockopt_on,sizeof(int))<0)
		logErrNum("init/setsockopt() failed returning %d",WSAGetLastError());
	if (bind(nonblocking(sock),(struct sockaddr*)&addr,szAddr)<0)
		logErrNum("init/bind() failed returning %d",WSAGetLastError());
	if (listen(sock,svrMAXCLIENTS)<0)
		logErrNum("init/listen() failed returning %d",WSAGetLastError());

	if (WSAGetLastError() == 0) {
		char *msg = malloc(100);
		sprintf(msg,"Daemon \"%s\" started successfully and serving on port %d.",peer,port);
		logAdd(msg);
		free(msg);
		}
	else {
		logAdd("Server failed to start!");
		return WSAGetLastError();
		}

	// Globals for server() and client() quantum-functions
	pBuf = malloc(svrPAKMAX);
	*nodeState(nodeSERVER,0) = &server;
	nodeSetValue(nodeSERVER,nodeCODE,nodeTRUE);

	return 0;	
	}


// Perform any cleanup for socket
int serverExit() {
	free(pBuf);
	// todo: close streams and free buffers etc
	#if __WIN32__
	WSACleanup();
	#endif
	return WSAGetLastError();
	}


// make the passed socket non-blocking so accept() returns straight away for multiplexed model
// - if no incoming requests, returns EAGAIN or EWOULDBLOCK state
int nonblocking(int socket) {
	#if __WIN32__
	ioctlsocket(socket,FIONBIO,&sockopt_on);
	#else
	fcntl(socket,F_SETFL,fcntl(socket,F_GETFL)|O_NONBLOCK);
	#endif
	return socket;
	}


// Return pointer to fdset filled with passed file-descriptor ready for a select() call
fd_set *fdsetInit(int fd) {
	FD_ZERO(&fdset);
	FD_SET(fd,&fdset);
	to.tv_sec = to.tv_usec = svrDELAY;
	return &fdset;
	}


// Process message in iBuf which should be a complete HTTP GET request
// - iPtr is put back to 0 so next message fills from start of iBuf
void streamProcess(streamInfo *stream) {
	char *rqst, *end, *msg = stream->iBuf;
	if (strncmp("GET /",msg,5)==0) {

		// Extract request path & query-string
		rqst = end = msg+4;
		while(*++end > ' ');
		*end = '\0';
		printf("Request:\"%s\"\n",rqst);

		// Exit if /stop requested
		if (strcmp("/stop",rqst)==0) nodeExit();

		// Send test response back
		send(stream->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nStink eh?",134,0);
		}
	else {
		send(stream->fd,"HTTP/1.1 200 OK\r\nDate: Mon, 31 Jul 2006 22:27:14 NZST\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: 9\r\n\r\nNo GET!!!",134,0);
		logAdd("Peerd only supports GET requests currently!");
		}
	stream->iPtr = 0; // reset iPtr ready for next message
	}


// Create new client-node and streamInfo structure from passed file-descriptor
// - if fd is NULL, then try and create one by resolving the resource string
void streamOpen(int fd, char *resource) {
	if (fd == NULL) {
		// if resource is /^[./]/ then its a file
		// - file will have different packet size etc
		// - may need to include &recv/&read etc in streamInfo struct
		}
	if (fd < 0) return logErrMsg("Couldn't open resource \"%s\"",resource);
	logAddNum("New connection: Stream%d.",fd);
	// Create new streamInfo structure and allocate buffers
	streamInfo *stream = malloc(sizeof(streamInfo));
	stream->fd = fd;
	stream->iBuf = malloc(svrBUFSIZE);
	stream->oBuf = malloc(svrBUFSIZE);
	stream->iPtr = stream->oPtr = stream->tPtr = 0;

	// Create new client-node in clients-loop and add the new streamInfo
	node nc = nodeGetValue(nodeCLIENTS,nodeLOOP);
	nc = nodeLoopInsert(nc,0);
	nodeSetValue(nodeCLIENTS,nodeLOOP,nc);
	nodeSetValue(nc,nodeCODE,nodeTRUE);
	*nodeState(nc,0) = &client;
	*nodeState(nc,nodeSTREAM) = stream;
	}


// Close the passed stream, free its resources and remove from clients-loop
void streamClose(streamInfo *stream) {
	printf("Stream%d closed.\n",stream->fd);
	//nodeLoopRemove(this); // NOTE: reduction not handling PREV
	free(stream->iBuf);
	free(stream->oBuf);
	free(stream);
	}


// Each of the stream nodes points to this function in its State
void client() {

	// Get pointer to the streamInfo structure in current nodal context (this)
	streamInfo *stream = *nodeState(this, nodeSTREAM);
	fd = stream->fd;
	char *iBuf = stream->iBuf, *oBuf = stream->oBuf;
	int n, i = 0;

	// If any data to recieve, read a packet
	if (select(fd+1,fdsetInit(fd),NULL,NULL,&to)>0) {
		if ((n = recv(fd,pBuf,svrPAKSIZE,0)) > 0) {
			// Some bytes were read, append to current message (loop last packet if msg too big)
			if (stream->iPtr > svrBUFSIZE-svrPAKSIZE) stream->iPtr -= svrPAKSIZE;
			while (n--)  // Append current msg, for each complete msg, process it & reset iPtr
				if ((iBuf[stream->iPtr++] = pBuf[i++]) != term[stream->tPtr++]) stream->tPtr = 0;
				else if (term[stream->tPtr] == 0) streamProcess(stream);
			}
		else if (n == 0) streamClose(stream); // Zero bytes were read, do orderly termination
		else logErrNum("client/recv() failed returning %d",WSAGetLastError());
		}

	// Data to send?
	//if (select(fd+1,NULL,fdsetInit(fd),NULL,&to)>0) {
		// write a packet from outbuf
		//int len = svrPAKSIZE; // or less
		//if (send(fd,oBuf+oPtr,len,0)<0) logErr("send() failed!");
	//	}

	}


// Function called by each stream-node in network's reduction loop
// - Checks if any new connections waiting on listening socket,
//   if so accept and call streamOpen() with new file-descriptor
void server() {
	if (select(sock+1,fdsetInit(sock),NULL,NULL,&to)>0)
		if ((fd = nonblocking(accept(sock,NULL,NULL)))>0) streamOpen(fd,NULL);
		else logErrNum("server/accept() failed returning %d",WSAGetLastError());
	}