多台机器间的数据同步

大家好,我目前就职于一家工业制造公司,我的email是wuxfei@gmail.com,工作近3年时间了。在工作中经常会遇到这样的问题,有多台机器可以处理多种工件。若A机器在处理a种工件后,得让B机器或更多地机器知道A机器已经处理过一个a种工件。


为了能满足项目需求,并提高该功能模块的可移植性,我设计了一个类,并提供相应的一些调用接口。思路如下:每当某台机器处理了某工件后,它便以广播的形式告知其他机器,并在收到回馈数量为其他机器数量总和时,则认为其他所有机器都收到了同步消息,即可在同步列表中删除该条同步信息。

上代码:

接口:

class SYNCHRO_API CXFSynchro  
{
public:
	//nBakCount为几机备份,>=2。
	bool InitiaSynchro(int nBakCount);

	//向其他机器发送同步信息,将该条数据发往其他机器。
	int SendSynchro(string &strItem);
	
	//重写这个类,处理其他机器发送的同步信息。子类函数结尾处必须调用父类函数以便告知发送者:你已经收到了对方的同步数据。
	virtual void OnSynchro(string &strItem);

	//获取还没有收到确认信息的同步数据。返回未确认的个数.主要是为了方便在界面显示未同步的数据。
	int GetNotACK(CStringArray &strNotACKArray);
	
public:
	CXFSynchro(UINT nPort);
	virtual ~CXFSynchro();
	
private:
	void SynchroThread();
	
private:
	map<string, int> m_WaitSynchroMap;
	CRITICAL_SECTION m_cs;
	int m_nBakCount;
	bool m_bSockOK;
	bool m_bStarting;
	UINT m_Localsock;
	UINT m_SendSock;
	UINT m_nSynchroPort;
	friend void SynchroThread(LPVOID lp);
};


源码如下:

CXFSynchro::CXFSynchro(UINT nPort)
{
	InitializeCriticalSection(&m_cs);
	m_WaitSynchroMap.clear();
	m_nSynchroPort = nPort;
	m_bSockOK = true;
	m_bStarting = false;

	WSADATA wsdata;
	WSAStartup(0x0202, &wsdata);

	g_addrSynchro1.sin_family = AF_INET;
	g_addrSynchro1.sin_addr.s_addr = INADDR_BROADCAST;
	g_addrSynchro1.sin_port = htons(m_nSynchroPort);
	memcpy(&g_addrSynchro2, &g_addrSynchro1, sizeof(sockaddr_in));
	
	char opt = true;
	m_SendSock = WSASocket(AF_INET,SOCK_DGRAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
	setsockopt(m_SendSock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
	
	sockaddr_in addLocal;
	addLocal.sin_family = AF_INET;
	addLocal.sin_addr.s_addr = 0;
	addLocal.sin_port = htons(m_nSynchroPort);
	opt = true;
	m_Localsock = socket(AF_INET, SOCK_DGRAM, 0);
	setsockopt(m_Localsock, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt));
	
	if (0 != bind(m_Localsock, (SOCKADDR*)&addLocal, sizeof(addLocal)))
	{
		m_bSockOK = false;
	}
}

CXFSynchro::~CXFSynchro()
{
	DeleteCriticalSection(&m_cs);
	g_bExitSynchro = true;
	closesocket(m_Localsock);
	closesocket(m_SendSock);
	Sleep(500);
}

int CXFSynchro::SendSynchro(string &strItem)
{	
	char szSend[1024*8];
	ZeroMemory(szSend, sizeof(szSend));
	szSend[0] = DATA_TYPE_SYN;
	strcat(szSend+1, strItem.c_str());

	EnterCriticalSection(&m_cs);
	m_WaitSynchroMap[strItem] = 0;
	int n = sendto(m_SendSock, szSend, 1+strlen(strItem.c_str()), 0, (sockaddr*)&g_addrSynchro1, sizeof(g_addrSynchro1));
	LeaveCriticalSection(&m_cs);
	return n;
}

void SynchroThread(LPVOID lp)
{
	while(!g_bExitSynchro)
	{
		((CXFSynchro*)lp)->SynchroThread();
		Sleep(300);
	}
}	

bool CXFSynchro::InitiaSynchro(int nBakCount)
{
	m_nBakCount = nBakCount;
	assert(m_nBakCount>=2);

	if (m_bSockOK && !m_bStarting)
	{
		m_bStarting = true;
		_beginthread(::SynchroThread, 0, this);
	}
	return m_bStarting;
}

void CXFSynchro::SynchroThread()
{
	char szBuff[8096];
	ZeroMemory(szBuff, sizeof(szBuff));
	int nAddrLen = sizeof(g_addrSynchro2);
	if (1>=recvfrom(m_Localsock, szBuff, sizeof(szBuff), 0, (sockaddr*)&g_addrSynchro2, &nAddrLen))
	{
		return;
	}
	const char dataType = szBuff[0];
	string strItem(szBuff+1);

	if (DATA_TYPE_SYN==dataType)//同步帧
	{
		EnterCriticalSection(&m_cs);
		if (m_WaitSynchroMap.end() == m_WaitSynchroMap.find(strItem))//若是其他机器挑起的
		{
			OnSynchro(strItem);
		}
		LeaveCriticalSection(&m_cs);
	} 
	else//确认帧
	{
		EnterCriticalSection(&m_cs);
		if (m_WaitSynchroMap.end() != m_WaitSynchroMap.find(strItem))//若是自己挑起的
		{
			m_WaitSynchroMap[strItem] = 1+m_WaitSynchroMap[strItem];
			if (m_WaitSynchroMap[strItem] >= m_nBakCount)
			{
				m_WaitSynchroMap.erase(strItem);
			}
		}	
		LeaveCriticalSection(&m_cs);
	}
}

void CXFSynchro::OnSynchro(string &strItem)
{
	char szSend[1024*8];
	ZeroMemory(szSend, sizeof(szSend));
	szSend[0] = DATA_TYPE_ACK;
	strcat(szSend+1, strItem.c_str());

	EnterCriticalSection(&m_cs);
	sendto(m_SendSock, szSend, 1+strlen(strItem.c_str()), 0, (sockaddr*)&g_addrSynchro1, sizeof(g_addrSynchro1));
	LeaveCriticalSection(&m_cs);
}

int CXFSynchro::GetNotACK(CStringArray &strNotACKArray)
{
	strNotACKArray.RemoveAll();
	map<string,int>::iterator iter;
	EnterCriticalSection(&m_cs);
	for (iter=m_WaitSynchroMap.begin(); iter!=m_WaitSynchroMap.end(); iter++)
	{		
		CString str = iter->first.c_str();
		strNotACKArray.Add(str);
	}
	LeaveCriticalSection(&m_cs);
	return strNotACKArray.GetSize();
}


本人能力有限,如有疑问可联系我 wuxfei@gmail.com。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值