C Board  

Go Back   C Board > General Programming Boards > Networking/Device Communication

Reply
 
LinkBack Thread Tools Display Modes
Old 02-26-2005, 11:04 AM   #1
Registered User
 
Join Date: Jul 2002
Posts: 47
Select handling more then 500 connections

Select is giving me trouble when I have more then 500 connections.
My errorhandler is telling me the system seg faults when it tries to use the FD_SET command once I get over 500 or so connections. This mainly happens when my program is accepting connections. Once someone is already connected it does not seem to have a problem in this area, but new connections can cause the segmentation fault. if anyone knows why this is doing this please let me know.

Here is the code for my Socket_Core

Code:
void cSCore::runcore(void)
{
	/*Lets Initialize Some Variables*/
	int *lsfd = new int; //Listening File Descriptor
	int *nsfd = new int; //Sfd For New Connections
	int returnval;
	int *maxfd = new int;
	char *buffer; //Temporary Message Buffer
	char *charbuffer = new char[1];
	struct sockaddr_in *newc = new sockaddr_in;
	fd_set *cset = new fd_set;
	fd_set *master = new fd_set;
	memset(charbuffer,0,1);
	*lsfd = Socket->cs_serve(Port);
	int *optval = new int;
	*optval = 1;
	setsockopt(*lsfd,SOL_SOCKET,SO_REUSEADDR,optval,sizeof(*optval));
	//FD_ZERO(cset);
	FD_ZERO(master);
	FD_ZERO(cset);
	FD_SET(*lsfd, master); //Add the listening sfd to the FD set
	*maxfd = *lsfd;
	sMainUsers *tempuser;
	while(enabled)
	{

		*cset = *master;	
		select((*maxfd)+1,cset,NULL,NULL,NULL);
		if(FD_ISSET(*lsfd, cset)) //If It is a New Connection
		{
			*nsfd = accept(*lsfd,NULL,(socklen_t *)sizeof(*newc));
			ErrorHandler->ProduceError(0,"cSCore::runcore()","New Connection Received");
			if(!UserHandler->AddUser(*nsfd,"unsupported"))
			{
				ErrorHandler->ProduceError(0,"cSCore::runcore()","Failed To Add User");
				close(*nsfd);
			}
			else
			{
				info("cSCore::runcore()","Adding to FD Set");
			FD_SET(*nsfd,master);
			if(*nsfd > *maxfd)
				*maxfd = *nsfd;
			}
				
		}
		else
		{
			ErrorHandler->ProduceError(0,"cSCore::runcore()","Data Received");
			tempuser = UserHandler->GetUser(0);
			//ErrorHandler->ProduceError(0,"cSCore::runcore()","UserPtr Caught");
			while(tempuser != NULL)
			{
				//ErrorHandler->ProduceError(0,"cSCore::runcore()","looping list");
				/*A User wants to send something*/
				if(FD_ISSET(tempuser->sfd,cset) && tempuser->sfd != *lsfd)
				{
					*nsfd = tempuser->sfd;
					ErrorHandler->ProduceError(0,"cSCore::runcore()","reading data");
					returnval = Socket->cs_read(*nsfd,charbuffer,1);
					//printf("Buffer value: %d\n",int(charbuffer[0]));
					//Check For Disconnects
					if(returnval == 0)
					{
						
						
						ChannelHandler->UserDisconnected(*nsfd);
						info("cSCore::runcore()","User Disconnected From Channels");
						UserHandler->RemoveUser(*nsfd);
						info("cSCore::runcore()","User Disconnected");
						
						close(*nsfd);
						FD_CLR(*nsfd,master);
						if(UserHandler->numusers == 0)
						{
							FD_ZERO(master);
							FD_SET(*lsfd,master);
						}
						break;
						
					}
					else
					{
						if(int(charbuffer[0]) == -1) //Byte 255
						{
							this->parsecmd(*nsfd,tempuser->UserBuffer->buffer);
							(tempuser->UserBuffer->done) = true;
						}
						else if((tempuser->UserBuffer->strsize) < ((tempuser->UserBuffer->buffersize) - 1))
						{
							tempuser->UserBuffer->buffer[(tempuser->UserBuffer->strsize)] = charbuffer[0];
							(tempuser->UserBuffer->strsize)++;
						}
						else if((tempuser->UserBuffer->buffersize) < 512)
						{
							(tempuser->UserBuffer->buffersize) += 5;
							buffer = new char[(tempuser->UserBuffer->buffersize)];
							memset(buffer,0,(tempuser->UserBuffer->buffersize));
							char *temp = tempuser->UserBuffer->buffer;
							strcpy(buffer,temp);
							buffer[(tempuser->UserBuffer->strsize)] = charbuffer[0];
							(tempuser->UserBuffer->strsize)++;
							tempuser->UserBuffer->buffer = buffer;
							delete [] temp;
							
						}
						else
						{
							(tempuser->UserBuffer->done) = true;
						}
						
						if((tempuser->UserBuffer->done) == true)
						{
							char *temp = tempuser->UserBuffer->buffer;
							tempuser->UserBuffer->buffer = new char[10];
							memset(tempuser->UserBuffer->buffer,0,10);
							(tempuser->UserBuffer->strsize) = 0;
							(tempuser->UserBuffer->buffersize) = 10;
							(tempuser->UserBuffer->done) = false;
							delete [] temp;
						}
					
					
					}
					break;
				}
				tempuser=tempuser->next;
			}

		}
		
	}
	close(*lsfd);
	delete master;
	delete cset;
	delete nsfd;
	delete maxfd;
	delete lsfd;
	delete [] buffer;
}
Thanks
Chronom1 is offline   Reply With Quote
Old 02-26-2005, 05:08 PM   #2
Registered User
 
Join Date: Sep 2004
Location: California
Posts: 3,020
You aren't even checking the return value of select. If select is giving you an error, you wouldn't even know it.
bithub is offline   Reply With Quote
Old 02-26-2005, 05:53 PM   #3
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,683
delete master;
delete cset;
delete nsfd;
delete maxfd;
delete lsfd;
delete [] buffer;
All these are small variables - dynamic allocation of them is pretty pointless.

> char *charbuffer = new char[1];
This is especially pointless. You also don't delete it, but you do delete buffer, which is probably not what you wanted.

Try splitting the code into several smaller functions. You have so much code, with so much indentation that it's hard to see what is going on.
Using tabs for indentation is a bit of a problem on this board, since the default tabstop width is quite large, thus exagerating the amount of indentation.
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 02-27-2005, 12:53 PM   #4
Registered User
 
Join Date: Jul 2002
Posts: 47
Alright,
Thanks for the help,
I just realized what you meant about me deleting buffer instead of charbuffer.

I know that the allocation is minimal, but the program is so huge that I am trying to keep as much out of the stack as possible. I do know that it is crashing here though. I am going to try reading the return value of select and see what that gets me.

Thanks,

Is there a max connections on Select?
and if so what is the limit?
Chronom1 is offline   Reply With Quote
Old 02-27-2005, 01:17 PM   #5
and the hat of Jobseeking
 
Salem's Avatar
 
Join Date: Aug 2001
Location: The edge of the known universe
Posts: 21,683
> Is there a max connections on Select?
Yes
Code:
/* Maximum number of file descriptors in `fd_set'.  */
#define FD_SETSIZE              __FD_SETSIZE
> I do know that it is crashing here though.
Yeah, but if you're trashing memory, this is almost certainly not the cause (only the effect)

> I am trying to keep as much out of the stack as possible.
Unless you're working with large arrays, I don't think its worth doing - certainly not if you're going to end up causing memory leaks with faulty memory allocation and deletion.

> tempuser->UserBuffer->done
If you create a couple of functions to hide all this detail, the code will be a lot clearer

Like
Code:
AddCharToUserBuffer( tempuser, ch );
MarkUserBufferComplete( tempuser );
__________________
If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.

Salem is offline   Reply With Quote
Old 02-27-2005, 03:20 PM   #6
Registered User
 
Join Date: Jul 2002
Posts: 47
Alright,
I did check the select and hers what I got
after the last connection before it segfaults select returns a 1 but the loop does not find a new connection or any data to be read. Then it does the same thing a second time and after that seg faults..
also here is a bit of cleaned up code.
Code:
/****************************************************************/
/*		FileName: cSCore.cpp				*/
/*		Author: David Estes(Chrono)			*/
/*		CopyRight 2004,2005 David Estes			*/
/*		Under the GPL License				*/
/*		FOR NON-COMMERCIAL USE ONLY			*/
/****************************************************************/
//====================
//Revisement History |
//====================
//02/23/2005 -- Moved Several Functions into cSCore-2.cpp to make file smaller
//
//
//====================
#include"cSCore.h"
#include"getarg.h"
void cSCore::runcore(void)
{
	/*Lets Initialize Some Variables*/
	int lsfd; //Listening File Descriptor
	int nsfd; //Sfd For New Connections
	int returnval;
	int maxfd = 0;
	char *buffer; //Temporary Message Buffer
	char *charbuffer = new char[1];
	struct sockaddr_in newc;
	fd_set *cset = new fd_set;
	fd_set *master = new fd_set;
	memset(charbuffer,0,1);
	lsfd = Socket->cs_serve(Port);
	int optval = 1;
	setsockopt(lsfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval));
	setsockopt(lsfd,SOL_SOCKET,SO_LINGER,&optval,sizeof(optval));
	//FD_ZERO(cset);
	FD_ZERO(master);
	FD_ZERO(cset);
	FD_SET(lsfd, master); //Add the listening sfd to the FD set
	maxfd = lsfd;
	sMainUsers *tempuser;
	int SelReturnVal=0;
	printf("Max FD_SIZE = %d\n",FD_SETSIZE);
	while(enabled)
	{

		*cset = *master;	
		SelReturnVal = select((maxfd)+1,cset,NULL,NULL,NULL);
		printf("Select Returned %d\n",SelReturnVal);
		if(FD_ISSET(lsfd, cset)) //If It is a New Connection
		{
			nsfd = accept(lsfd,NULL,(socklen_t *)sizeof(newc));
			ErrorHandler->ProduceError(0,"cSCore::runcore()","New Connection Received");
			if(!UserHandler->AddUser(nsfd,"unsupported"))
			{
				ErrorHandler->ProduceError(0,"cSCore::runcore()","Failed To Add User");
				close(nsfd);
			}
			else
			{
				info("cSCore::runcore()","Adding to FD Set");
			FD_SET(nsfd,master);
			if(nsfd > maxfd)
				maxfd = nsfd;
			}
				
		}
		else
		{
			ErrorHandler->ProduceError(0,"cSCore::runcore()","Data Received");
			tempuser = UserHandler->GetUser(0);
			//ErrorHandler->ProduceError(0,"cSCore::runcore()","UserPtr Caught");
			while(tempuser != NULL)
			{
				//ErrorHandler->ProduceError(0,"cSCore::runcore()","looping list");
				/*A User wants to send something*/
				if(FD_ISSET(tempuser->sfd,cset) && tempuser->sfd != lsfd)
				{
					nsfd = tempuser->sfd;
					ErrorHandler->ProduceError(0,"cSCore::runcore()","reading data");
					returnval = Socket->cs_read(nsfd,charbuffer,1);
					if(returnval == 0) //Check To See If The User Disconnected
					{
						
						//UserDisconnected -- Notify Channels	
						ChannelHandler->UserDisconnected(nsfd);
						info("cSCore::runcore()","User Disconnected From Channels");
						//Notify UserHandler Of Disconnect and Remove All Memory Allocation of User
						UserHandler->RemoveUser(nsfd);
						info("cSCore::runcore()","User Disconnected");
						close(nsfd);
						FD_CLR(nsfd,master);
						printf("%s%sUsers Connected: %d%s\n",FOREBLACK,BACKGREEN,UserHandler->numusers,NORMAL);
						if(UserHandler->numusers == 0)
						{
							FD_ZERO(master);
							FD_SET(lsfd,master);
						}
						break;
						
					}
					else
					{
						sUserBuffers *UserBuffer = tempuser->UserBuffer;
						if(int(charbuffer[0]) == -1) //Byte 255
						{
							this->parsecmd(nsfd,GetUserBufferData(UserBuffer));
							MarkUserBufferComplete(UserBuffer);
						}
						else
						{
							if(AddCharToUserBuffer(UserBuffer,charbuffer[0]) == -1)
								MarkUserBufferComplete(UserBuffer);
						}
						
						if(IsBufferComplete(UserBuffer))
							ResetUserBuffer(UserBuffer);	
					
					}
					break;
				}
				tempuser=tempuser->next;
			}

		}
		
	}
	close(lsfd);
	delete master;
	delete cset;
	delete [] charbuffer;
}
Chronom1 is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
temperature sensors danko C Programming 22 07-10-2007 07:26 PM
brace-enclosed error jdc18 C++ Programming 53 05-03-2007 05:49 PM
Directional Keys - Useing in Console RoD C++ Programming 38 10-06-2002 04:42 PM
FAQ: Directional Keys - Useing in Console RoD FAQ Board 38 10-06-2002 04:42 PM


All times are GMT -6. The time now is 05:34 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22