⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpipsck.cpp

📁 mini http server,可以集成嵌入到程序中,实现简单的web功能
💻 CPP
📖 第 1 页 / 共 4 页
字号:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int Internal_initPassiveSocket( PIObject *pThis, TCPIPSocketData *pData )
{
	/* automatic variables */
	int iOne=1;

	assert( pData );

	/*
	** Make the socket 
	*/
	pData->iSocket = ::socket( AF_INET, SOCK_STREAM, 0);
	if ( pData->iSocket<0 )
		{
		CONFIG_ERR(pThis, "socket() failed" );
		return PIAPI_ERROR;
		};

	/*
	**
	** Attempt to bind to port
 	**
	*/ 
	pData->iSize=sizeof( struct sockaddr_in );
	pData->tAddr.sin_family = AF_INET;

	if (PIUtil_stricmp( pData->pMainSocketData->pHost, VALUE_INADDR_ANY )
	&& PIUtil_stricmp( pData->pMainSocketData->pHost, VALUE_INADDR_ZERO ))
		{
		/*
		** Sequence for binding to a specific address
		*/
		struct hostent *phe = ::gethostbyname( pData->pMainSocketData->pHost );
		if ( !phe )
			{
			CONFIG_ERR(pThis, "gethostbyname() failed" );
			return PIAPI_ERROR;
			};

		/* --- setup local address structure -- */
		memcpy( &(pData->tAddr.sin_addr.s_addr), phe->h_addr, phe->h_length );
		}
	else
		{
		/*
		** Sequence for binding to any address
		*/
		pData->tAddr.sin_addr.s_addr=htonl(INADDR_ANY);
		}

	pData->tAddr.sin_port = htons( pData->pMainSocketData->iPort );

	/*
 	** Allow host,port to be reused (or attempt to reuse existing host,port)
	*/
	if ( ::setsockopt( pData->iSocket, SOL_SOCKET, SO_REUSEADDR, 
		(const char *)&iOne, sizeof( iOne ) )!=0 )
		{
		CONFIG_ERR(pThis, "setsockopt() failed for SO_REUSEADDR" );
		return PIAPI_ERROR;
		};

	/*
	** Disable nagle algorithm
	*/
	if ( ::setsockopt( pData->iSocket, IPPROTO_TCP, TCP_NODELAY,
		(const char *)&iOne, sizeof( iOne ) )!=0 )
		{
		CONFIG_ERR(pThis, "setsockopt() failed for TCP_NODELAY" );
		return PIAPI_ERROR;
		};

	if ( ::bind( pData->iSocket, (struct sockaddr *)&(pData->tAddr), 
		pData->iSize)<0) 
		{
		const char *pError = "";
		switch( errno )
			{	
			case EACCES:
				pError = szBindFailedAccess;
				break;

			case EINVAL:
#if POSIX
			case EADDRINUSE:
#endif
				pError = szBindFailedInUse;
				break;

			default:;
			};

		PILog_addMessage(
			PIObject_getDB( pThis ),
			PIObject_getConfigurationDB( pThis ), PILOG_ERROR,
			"Failed to bind to port %d.%s", pData->pMainSocketData->iPort,
			pError );

		return PIAPI_ERROR;
		};
		
	if ( ::listen( pData->iSocket, LISTEN_QUEUE_SIZE )<0 )
		{
		CONFIG_ERR(pThis, "listen() failed" );
		return PIAPI_ERROR;
		};

	/*
	** Done
	*/
	return PIAPI_COMPLETED;
}

/*____________________________________________________________________________*\
 *
 Function:		Internal_getHostEnt
 Synopsis:		private
 Description:
	returns a struct hostent *, given either an id address or hostname
	as parameter.
\*____________________________________________________________________________*/
static struct hostent *Internal_getHostEnt( const char *pHost )
{
	int i;
	int iIsAddr=1;
	int iLen;
	struct hostent *phe;

	/*
	** If the string consists only of decimal digits and '.'
	** assume its an IP address
	*/
	if ( !pHost ) return 0;
	iLen = strlen( pHost );
	for(i=0; i<iLen; i++)
		{
		if ( !isdigit( pHost[i] ) && pHost[i]!='.' )
			{ 		
			iIsAddr=0; 
			break; 
			};
		};

	/* --- get hostent * --- */
	phe=0;
	if ( iIsAddr )
		{
		struct in_addr tAddr;
		u_long ul;
		int iSize;

		ul = inet_addr( pHost );
		iSize = sizeof( struct in_addr );
		memcpy( &tAddr, &ul, iSize );
		phe = gethostbyaddr( (const char *)&tAddr, iSize, AF_INET);
		}
	else
		{
		phe = gethostbyname( pHost );
		};
	return phe;
}

/*____________________________________________________________________________*\
 *
 Function:		 Internal_connect
 Synopsis:
 Description:
	Open a connection to a remote host
\*____________________________________________________________________________*/
PUBLIC_PIAPI int Internal_connect( PIObject *pThis,
		const char *pHostName, int iPort )
{
	/* automatic variables */
	TCPIPSocketData *pData=(TCPIPSocketData *)PIObject_getUserData( pThis );
	struct hostent *phe;

	assert( pData );

	/*
	** Make the socket
	*/
	pData->iSocket = ::socket( AF_INET, SOCK_STREAM, 0);
	if ( pData->iSocket==SOCKET_ERROR )
		{
		PIPlatform_setLastError( PIAPI_EXHAUSTED );
		CONFIG_ERR(pThis, "socket() failed" );
		return PIAPI_ERROR;
		};

	/*
	** setup pData->tAddr with remote host information.
	*/
	phe=Internal_getHostEnt( pHostName );
	if ( !phe )
		{
		PIPlatform_setLastError( PIAPI_ERROR );
		return PIAPI_ERROR;
		};

	pData->iSize=sizeof( struct sockaddr_in );
	pData->tAddr.sin_family = AF_INET;
	memcpy( &(pData->tAddr.sin_addr), phe->h_addr, phe->h_length );
	pData->tAddr.sin_port = htons( iPort );

	/*
 	** bind 
	*/
	/* or not to bind */

	/*
 	** connect
	*/
	if ( connect( pData->iSocket, (struct sockaddr *)&(pData->tAddr), 
			pData->iSize )<0 )
		{
		PIPlatform_setLastError( PIAPI_ERROR );
		return PIAPI_ERROR;
		};

	/* ---
	**
	**
	** This is a new connection. Look at the flags and variable names
	** to see what lookups should occur and where the data is put
	**
	**
	--- */

	/* --- should this object set the PeerIP address? --- */
	int iFlags = pData->pMainSocketData->iFlags;

	/* ---
	Set PeerAddress variable, if applicable
	--- */
	/* ---
	When the hostname is unavailable just have it turn up blank
#	define TEXT_UNAVAILABLE	"** Unavailable **"
	--- */
#	define TEXT_UNAVAILABLE	""

	if ( iFlags & FLG_SETREMOTEADDRESS )
		{
		/* --- set remote Address ? --- */
		DBInfo *pIPInfo = pData->pMainSocketData->pPeerAddressVariable;
		if ( pIPInfo )
			{
			/* ---
			inet_ntoa is not thread safe, protect access to it
			--- */
			PIPlatform_beforeUnsafeBlock();

			/* --- convert the peer ip to a string if we have the ip --- */
			const char *pPeerAddress = 0;
			pPeerAddress = ::inet_ntoa( pData->tAddr.sin_addr );

			PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
				pIPInfo->pFKVariableName, (void *)pPeerAddress,
				pIPInfo->iFlags | PIDBFLAG_FASTKEY );
			PIPlatform_afterUnsafeBlock();
			};

		if ( iFlags & FLG_DNSREVERSELOOKUP )
			{
			/* --- set remote hostname ? --- */
			DBInfo *pHostInfo = pData->pMainSocketData->pPeerHostVariable;
			if ( pHostInfo )
				{
				/* ---
				inet_ntoa is not thread safe, protect access to it
				--- */
				PIPlatform_beforeUnsafeBlock();

				/* --- if we have the ip structure, lookup the hostname --- */
				struct hostent *pEnt;
				pEnt = ::gethostbyaddr(
					(const char *)&(pData->tAddr.sin_addr),
					sizeof(pData->tAddr.sin_addr), AF_INET ); 
				PIDB_add( PIObject_getDB( pThis ), pHostInfo->iType,
					pHostInfo->pFKVariableName,
					(void *)( pEnt ? pEnt->h_name : TEXT_UNAVAILABLE ),
					pHostInfo->iFlags | PIDBFLAG_FASTKEY ); 
				PIPlatform_afterUnsafeBlock();
				};
			};

			/* ---
			set ServerPort variable
			--- */
			DBInfo *pPortInfo = pData->pMainSocketData->pServerPortVariable;
			if ( pPortInfo ) {
				char szPort[6];
				char *pPort = szPort;
				sprintf(pPort, "%lu", iPort);
				PIDB_add( PIObject_getDB( pThis ), pPortInfo->iType, pPortInfo->pFKVariableName,
					(void *)pPort, 0 );
			};
		};

	/* ---
	Set LocalAddress if applicable
	--- */
	if ( iFlags & FLG_SETLOCALADDRESS )
		{
		DBInfo *pIPInfo = pData->pMainSocketData->pLocalAddressVariable;
		if ( pIPInfo )
			{
			struct sockaddr_in tLocalAddr;
			int iLocalSize = sizeof( struct sockaddr_in );

			for(;;)
				{
				/* --- get local socket information --- */
				if ( ::getsockname( pData->iSocket,
						(struct sockaddr *)&tLocalAddr,
						&((uint)iLocalSize) )==-1 )
					{
					if ( errno==EINTR )
						{
						/* --- restart system call --- */
						PIThread_userYield();
						continue;
						};
					iLocalSize = 0;	/* indicate an error */
					};
				break;
				};

			if ( iLocalSize>0 )
				{
				/* ---
				inet_ntoa is not thread safe, protect access to it
				--- */
				PIPlatform_beforeUnsafeBlock();
	
				const char *pLocalAddress = 0;
	
				pLocalAddress = ::inet_ntoa( tLocalAddr.sin_addr );
				PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
					pIPInfo->pFKVariableName, (void *)pLocalAddress,
					pIPInfo->iFlags | PIDBFLAG_FASTKEY );

				PIPlatform_afterUnsafeBlock();
				}
			else
				{
				/* --- error --- */
				STDERR << "getsockname() failed, errno#" << errno << endl;
				PIDB_add( PIObject_getDB( pThis ), pIPInfo->iType,
					pIPInfo->pFKVariableName, (void *)"0.0.0.0",
					pIPInfo->iFlags | PIDBFLAG_FASTKEY );
				};	/* iLocalSize!=0 */

			};	/* pIPInfo!=NULL */
		};	/* iFlags & FLG_SETLOCALADDRRESS */

	/* ---
	Write send and receive timeout into the DB, to be overridden as
	necessary
	--- */
	assert( pFKRecvTimeout );
	assert( pFKSendTimeout );
	PIDB_add( PIObject_getDB( pThis ), PIDBTYPE_OPAQUE, pFKRecvTimeout,
		(void *)(pData->pMainSocketData->iRecvTimeout), PIDBFLAG_FASTKEY );
	PIDB_add( PIObject_getDB( pThis ), PIDBTYPE_OPAQUE, pFKSendTimeout,
		(void *)(pData->pMainSocketData->iSendTimeout), PIDBFLAG_FASTKEY );

	/*
	** Done
	*/
	return PIAPI_COMPLETED;
}

/*____________________________________________________________________________*\
 *
 Function:
 Synopsis:
 Description:
\*____________________________________________________________________________*/
int MainSocketData::Accept( TCPIPSocketData *pData, PIObject *pNewSocket )
{
	/* --- automatic variables --- */
	int iNewS;
	TCPIPSocketData *pChildData;

	if ( !pNewSocket ) return PIAPI_ABORT;

	/* --- get data object of child class --- */
	pChildData=(TCPIPSocketData *)PIObject_getUserData( pNewSocket );

	/*
	** Accept a new connection
	*/
	iNewS=-1;

	/* --- note the new accepting IO object, so it can be deleted --- */
	pAcceptingIOObject = pNewSocket;

	for(;;)
		{		

		/* --- test that accept is possible --- */
		if ( PIPlatform_pollNetFD( pData->iSocket, PIPLATFORM_POLL_READ,
			iAcceptTimeout ) <=0 )
			{
			break;
			};

#if POSIX
		/* ---
		wait to acquire the POSIX lock to stop multiple 	
		processes colliding on the accept 
		--- */
		if ( iFAcceptLockFD!=-1 )
			{
			/* ---
			Lock
			--- */
			if ( PIPlatform_advisaryLockFd( iFAcceptLockFD )!=PIAPI_COMPLETED )
				{
				/* --- an error occurred in lock --- */
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"TCPIPIO: Error obtaining lock (locking failed) errno: \
'%d'.\
 Removing lockfile to force server shutdown.", errno );

				/* ---
				remove lockfile to shutdown entire server
				see notes above.
				--- */
				::unlink( pFAcceptLockFile );	/* --- remove file --- */
				return PIAPI_ABORT;
				};
			};

#endif

		/* --- accept the connection --- */
		iNewS=::accept( pData->iSocket, 
				(struct sockaddr *)&(pChildData->tAddr),
				&((uint)pChildData->iSize) );

		if ( iFAcceptLockFD!=-1 )
			{
			/* ---
			Release the lock
			--- */
			if ( PIPlatform_advisaryUnlockFd( iFAcceptLockFD )!=PIAPI_COMPLETED )
				{
				PILog_addMessage( pDB, pConfigDB, PILOG_ERROR,
					"TCPIPIO: Error releasing lock, (unlock failed) errno:\
'%d'.", errno );
				::unlink( pFAcceptLockFile );	/* --- remove file --- */
				return PIAPI_ABORT;
				};
			};

		/* ---
		Some cases of error on accept are restartable, don't return an error
		for those
		--- */
		if ( iNewS==-1 )
			{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -