大家好,我目前就职于一家工业制造公司,我的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。