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

📄 server.cpp

📁 KepWare的OPC Client 示例.面向C
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		if (pGroup == m_pGroupHead)
			m_pGroupHead = pNext;

		// Decrement the group count:
		--m_cdwGroups;

		// Delete the group object:
		delete pGroup;
		}
	else
		{
		// Since CKGroup object was not deleted, it should be flagged as invalid
		// becuase it no longer has an associated OPC Group in OPC Server.
		pGroup->SetValid (false);
		}
	}

// **************************************************************************
// RemoveAllGroups ()
//
// Description:
//	Remove all OPC Groups from OPC server, and delete associated CKGroup
//  objects if asked.
//
// Parameters:
//  bool		bDelete		Delete group objects after removing.  true by 
//							 default.
//
// Returns:
//  void
// **************************************************************************
void CKServer::RemoveAllGroups (bool bDelete /* = true */)
	{
	// Start with the head of linked list and work our way up chain:
	CKGroup *pGroup = m_pGroupHead;

	// Remove OPC Groups and delete assoicated CKGroup objects:
	if (bDelete)
		{
		// Work our way up linked list.  pGroup will be NULL when we reach
		// end, and we will then break out of loop.
		while (pGroup)
			{
			// Get the group's next item before we delete group.  The
			// next item will be the new head of linked list.
			m_pGroupHead = pGroup->GetNext ();

			// Remove and delete:
			RemoveGroup (pGroup, bDelete);

			// Next group to processes is the new head of the list:
			pGroup = m_pGroupHead;
			}
		}

	// Just remove the OPC Groups:
	else
		{
		// Work our way up linked list.  pGroup will be NULL when we reach
		// end, and we will then break out of loop.
		while (pGroup)
			{					
			// Remove the group:
			RemoveGroup (pGroup, bDelete);

			// Process next group in list:
			pGroup = pGroup->GetNext ();
			}
		}
	}

#define MAXGROUPNAMELEN	32	// impose a limit when generating a name


// **************************************************************************
// GenerateGroupName ()
//
// Description:
//	Check to see if a group name is in use.  If it is, then modify name so
//	that it is unique to this server.
//
// Parameters:
//  CString		&strName		Group name.  Must not be input as empty.
//								  Will be modified if needed.
//
// Returns:
//  bool - true if success
// **************************************************************************
bool CKServer::GenerateGroupName (CString &strName)
	{
	ASSERT (!strName.IsEmpty ());

	// If FindGroup() returns true, then name is in use and we need to
	// generate a new group name unique to this server:
	if (FindGroup (strName))
		{
		TCHAR szName [MAXGROUPNAMELEN + 1];
		TCHAR szSuffix [16];
		LPTSTR pch;
		int nSuffix;
		
		// Make a copy of the group name.  Use a TCHAR array so it will be
		// fast & easy to check each character using pointer math.
		lstrcpyn (szName, strName, _countof (szName));
		
		// Point to the last character (the -1 is needed since arrays are 0-based):
		pch = &szName [lstrlen (szName) - 1];


		//////////////////////////////////////////////////////////////
		// Create a numerical suffix that should make name unique	//
		//////////////////////////////////////////////////////////////

		// If the last character is a number, then we will interpret all digits
		// a end of string as a suffix.  Once that suffix is parsed off, we will
		// increment it for the new name.
		if (_istdigit (*pch))
			{
			// Back up until we hit a non-digit:
			while (_istdigit (*pch))
				--pch;

			// Adjust forward one character so we now point to first
			// digit in numerical suffix:
			++pch;
			
			// Determine the current suffix and increment:
			nSuffix = _ttol (pch) + 1;
			}
		
		// Otherwise simply start a new series with the suffix "1":
		else
			{
			// Move forwared one character so we'll be pointing at
			// string's NULL terminator:
			++pch;
			nSuffix = 1;
			}


		//////////////////////////////////////////////////////////
		// Add new numerical suffix and validate resulting name	//
		//////////////////////////////////////////////////////////

		do
			{
			// Trim any existing numeric suffix from the name. (pch should
			// be pointing at first digit of suffix it it exists, or NULL
			// terminator of string if not.)
			*pch = 0;

			// Convert the suffix we just created to a string:
			wsprintf (szSuffix, _T("%d"), nSuffix);

			// Determine the length of name minus existing numerical suffix, if any:
			int nNameLen = lstrlen (szName);

			// Determin the length of the suffix we just created:
			int nSuffixLen = lstrlen (szSuffix);

			// If the name with new suffix will be longer than allowable maximum
			// (for logging) then truncate:
			if (nNameLen + nSuffixLen > MAXGROUPNAMELEN)
				{
				// Compute the number of characters we need to hack off:
				int nDif = MAXGROUPNAMELEN - (nNameLen + nSuffixLen);
				
				ASSERT (nDif < 0);

				// Adjust the length in preparation to truncate:
				nNameLen += nDif;
				pch += nDif;

				// Check for remaining chars and return false if we just can't fit
				// the suffix:
				if (nNameLen < 1)
					return (false);

				// If we make it here, then we can go ahead and truncate the name
				// by replacing the nNameLen'th character with a NULL terminator:
				szName [nNameLen] = 0;
				}

			// Append the suffix to the name:
			lstrcat (szName, szSuffix);

			// Validate the resulting name.  If FindGroup returns false, then
			// we know the new name is not currently in use.
			if (!FindGroup (szName))
				{
				// New name is not in use.  Assing it to strName for output and 
				// return true to indicate successful processing.
				strName = szName;
				return (true);
				}
			
			// If we make it here, we know new name is no good.  Increment the suffix
			// and try again.  We will continue to loop unitl the suffix results in a
			// good name or string length becomes too long.
			} while (++nSuffix > 0);
		
		// If we make it to here (not likely), then we've run out of
		// options.  Return false to indicate that we had problems.
		ASSERT (FALSE);
		return (false);
		}
	
	// If we made it here, then specified name is not presently in use.
	// No need to change it.  Just return true to indicate we successfully
	// processed name.
	return (true);
	}

// **************************************************************************
// FindGroup ()
//
// Description:
//	Search list of groups attached to this server for one with specified name.
//
// Parameters:
//  LPCTSTR		lpszName	Pointer to name string.
//
// Returns:
//  bool - true if group found.
// **************************************************************************
bool CKServer::FindGroup (LPCTSTR lpszName)
	{
	// Start with first group in linked list and work our way up the chain:
	CKGroup *pGroup = m_pGroupHead;

	// Keep looping we hit the end of the link list (where pGroup will be NULL):
	while (pGroup)			
		{
		// If the name of the current group is the same as lpszName, then
		// we can break out of loop.  Return true to indicate that group
		// was found.
		if (lstrcmpi (lpszName, pGroup->GetName ()) == 0)
			return (true);

		// Look at next group in list next time around:
		pGroup = pGroup->GetNext ();
		}

	// If we make it here, then we have looked at all of the groups in the
	// list and didn't find one with specified name.  Return false to
	// indicate group was not found.
	return (false);
	}

// **************************************************************************
// GetGroup ()
//
// Description:
//	Get pointer to group with specified name.
//
// Parameters:
//  LPCTSTR		lpszName	Pointer to name string.
//
// Returns:
//  CKGroup* - Pointer to group object, NULL if group not found.
// **************************************************************************
CKGroup* CKServer::GetGroup (LPCTSTR lpszName)
	{
	// Start with first group in linked list and work our way up the chain:
	CKGroup *pGroup = m_pGroupHead;

	// Keep looping we hit the end of the link list (where pGroup will be NULL):
	while (pGroup)			
		{
		// If the name of the current group is the same as lpszName, then
		// we can break out of loop.  Return pointer to group.
		if (lstrcmpi (lpszName, pGroup->GetName ()) == 0)
			return (pGroup);

		// Look at next group in list next time around:
		pGroup = pGroup->GetNext ();
		}

	// If we make it here, then we have looked at all of the groups in the
	// list and didn't find one with specified name.  Return NULL to indicate
	// group was not found.
	return (NULL);
	}


/////////////////////////////////////////////////////////////////////////////
// CKServer manipulators
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// SetProgID ()
//
// Description:
//	Set Prog ID of OPC Server we will be associated with.
//
// Parameters:
//	CString		&strProgID		Prog ID.
//
// Returns:
//  void
// **************************************************************************
void CKServer::SetProgID (CString &strProgID)
	{
	ASSERT (!strProgID.IsEmpty ());

	// Save Prog ID string as a member variable:
	m_strProgID = strProgID;
	}

// **************************************************************************
// SetRemoteMachine ()
//
// Description:
//	Set name of machine associated OPC Server will be running on.
//
// Parameters:
//  CString		&strRemoteMachine	Name of remote machine, NULL if local.
//
// Returns:
//  void
// **************************************************************************
void CKServer::SetRemoteMachine (CString &strRemoteMachine)
	{
	// Save machine name string as a member variables.  This string will be
	// empty if server will be running on the local machine.
	m_strRemoteMachine = strRemoteMachine;
	}


/////////////////////////////////////////////////////////////////////////////
// CKServer serialization
/////////////////////////////////////////////////////////////////////////////

// **************************************************************************
// Serialize ()
//
// Description:
//	Save or load server properties.
//
// Parameters:
//  CArchive		&ar			The archive to save or load server properties.
//
// Returns:
//  void
// **************************************************************************
void CKServer::Serialize (CArchive &ar)
	{
	// Save server properties:
	if (ar.IsStoring ())
		{
		//////////////////////////////
		// Save archive properties	//
		//////////////////////////////

		// Output current archive version.  If we add server properties that
		// must be made persistent, then we will have to update the archive
		// version so we know how to read the additional data.
		ar << CURRENT_VERSION;


		//////////////////////////////
		// Save server properties	//
		//////////////////////////////

		// Output info about associated OPC Server:
		ar << m_strProgID << m_strRemoteMachine;

		// Output flags in bit field:
		ar.Write (&m_bfFlags, sizeof (m_bfFlags));

		// Output number of groups so we will know how many block of group 
		// data follows when we read this archive later:
		ar << m_cdwGroups;


		//////////////////////////////////
		// Serialize all of our groups	//
		//////////////////////////////////
		
		//Start with head of linked list:
		CKGroup *pGroup = m_pGroupHead;

		// Keep looping we hit the end of the link list (where pGroup will be NULL):
		while (pGroup)			
			{
			// Call group's serialize function so that it can add its properties
			// to the archive:
			pGroup->Serialize (ar);

			// Process next group next time around:
			pGroup = pGroup->GetNext ();
			}
		}

	// Load server properties:
	else
		{
		DWORD dwSchema;
		DWORD dwIndex;


		//////////////////////////////
		// Load archive properties	//
		//////////////////////////////
		ar >> dwSchema;

		// dwSchema is really the archive version.
		switch (dwSchema)
			{
			case VERSION_1:
				//////////////////////////////
				// Load server properties	//
				//////////////////////////////

				// Input info about associated OPC Server:
				ar >> m_strProgID >> m_strRemoteMachine;

				// Input flags in bit field:
				ar.Read (&m_bfFlags, sizeof (m_bfFlags));

				// Input number of groups so we will know how many block of group 
				// data follows:
				ar >> m_cdwGroups;

				
				//////////////////////////////////
				// Serialize all of our groups	//
				//////////////////////////////////
				
				// Start with an empty linked list:
				ASSERT (m_pGroupHead == NULL);

				// Loop over expected number of groups:
				for (dwIndex = 0; dwIndex < m_cdwGroups; dwIndex++)
					{
					CKGroup *pGroup = NULL;

					// Wrap group serialization with exception handler in case
					// there is a problem, such as bad archive version etc.
					try
						{

⌨️ 快捷键说明

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