实现VC下基于消息机制的UDP连接的步骤

实现VC下基于消息机制的UDP连接的步骤

1. 声明变量

/***************** http://blog.csdn.net/elysium *************************/

/************************** MainFrm.H **********************************/

public:
HICON m_hIcon;
BOOL CreateAlarmSocket();
SOCKETm_sockAlarm;
UINTm_nAlarmPort;
CStringm_strAlarmAddr;
struct sockaddr_in m_srvaddrAlarm, m_sockaddrinAlarm;

...

afx_msg LRESULT OnReceiveAlarmSock(WPARAM wParam, LPARAM lParam);

2. 基本步骤

在项目头文件UDPDemo.H声明变量

#define WM_ALARMSOCKWM_USER + 200

TCHARm_szDataSource[255];//服务器计算机名称或文件DSN--Name of server machine or local cube file
TCHARm_szCatalog[255];//数据源名称--Name of default (initial) database (catalog)
TCHARm_szUserID[255];//用户名称
TCHARm_szPassword[255];//用户密码

TCHARm_szAlarmAddr[255];//报警Socket地址
TCHARm_szCallAddr[255];//语音Socket地址

BOOL CUDPDemoApp::InitInstance()
{
...
if (!AfxSocketInit())
{
MessageBox(NULL, "初始化SOCKET服务失败", "UdpDemo", MB_ICONEXCLAMATION | MB_OK);
return FALSE;
}
...
}
int CUDPDemoApp::ExitInstance()
{
WriteConfig(); //保存配置文件信息
CoUninitialize( ); //关闭COM组件库,释放COM资源
if (m_hOnlyMutex)
CloseHandle(m_hOnlyMutex);
return CWinApp::ExitInstance();
}
//读取INI文件
BOOL CUDPDemoApp::ReadConfig()
{
TCHAR exeFullPath[MAX_PATH];
CString strIniFile;
//GetModuleFileNameEx(NULL, exeFullPath, MAX_PATH);// Exists in PSAPI.H
::GetModuleFileName(NULL, exeFullPath, MAX_PATH);

strIniFile.Format("%s", exeFullPath);
exeFullPath[strIniFile.GetLength()-18] = '/0';
strIniFile.Format("%s", exeFullPath);
strIniFile += INIFILENAME;//"Config.INI";
try
{
::GetPrivateProfileString("DATABASE", "DataSource", LOCALHOST, m_szDataSource, MAX_PATH, strIniFile);
::GetPrivateProfileString("DATABASE", "Catalog", LOCALHOST, m_szCatalog, MAX_PATH, strIniFile);
::GetPrivateProfileString("DATABASE", "UserID", LOCALHOST, m_szUserID, MAX_PATH, strIniFile);
::GetPrivateProfileString("DATABASE", "Password", LOCALHOST, m_szPassword, MAX_PATH, strIniFile);

::GetPrivateProfileString("SOCKET", "AlarmRemoteHost", "127.0.0.1", m_szAlarmAddr, 16, strIniFile);
m_uiAlarmPort = ::GetPrivateProfileInt("SOCKET", "AlarmPort", 5001, strIniFile);

}
catch (CException *e)
{
e->ReportError();
e->Delete();
return FALSE;
}
return TRUE;
}
//配置INI文件
BOOL CUDPDemoApp::WriteConfig()
{
TCHAR exeFullPath[MAX_PATH];
CString strIniFile;
//GetModuleFileNameEx(NULL, exeFullPath, MAX_PATH);// Exists in PSAPI.H
::GetModuleFileName(NULL, exeFullPath, MAX_PATH);

strIniFile.Format("%s", exeFullPath);
exeFullPath[strIniFile.GetLength()-18] = '/0';
strIniFile.Format("%s", exeFullPath);
strIniFile += INIFILENAME;//"Config.INI";
try
{
::WritePrivateProfileString("DATABASE", "DataSource", m_szDataSource, strIniFile);
::WritePrivateProfileString("DATABASE", "Catalog", m_szCatalog, strIniFile);
::WritePrivateProfileString("DATABASE", "UserID", m_szUserID, strIniFile);
::WritePrivateProfileString("DATABASE", "Password", m_szPassword, strIniFile);

::WritePrivateProfileString("SOCKET", "AlarmRemoteHost", m_szAlarmAddr, strIniFile);
itoa(m_uiAlarmPort, strAlarmPort, 10);
::WritePrivateProfileString("SOCKET", "AlarmPort", strAlarmPort, strIniFile);
}
catch (CException *e)
{
e->ReportError();
e->Delete();
return FALSE;
}
return TRUE;
}
/********* MainFrm.CPP **********/
ON_MESSAGE(WM_ALARMSOCK, OnReceiveAlarmSock)
//建立报警Socket
BOOL CMainFrame::CreateAlarmSocket()
{
WORD wVersionRequested = MAKEWORD(2, 2);//采用WinSock2.2版本
WSADATA WSAData = {0};
int err;
err = WSAStartup(wVersionRequested, &WSAData);
if (0 != err)
{
MessageBox(_T("没有发现可用的 WinSock DLL"), _T("UdpDemo"), MB_ICONINFORMATION | MB_OK);
return FALSE;
}

if (LOBYTE(WSAData.wVersion) != LOBYTE(wVersionRequested) ||
HIBYTE(WSAData.wVersion) != HIBYTE(wVersionRequested))
{
MessageBox(_T("Winsock.dll 版本不匹配"), _T("UdpDemo -- http://blog.csdn.net/elysium"), MB_ICONINFORMATION | MB_OK);

WSACleanup();
return FALSE;
}
m_sockAlarm = socket(AF_INET, SOCK_DGRAM, 0);
if (INVALID_SOCKET == m_sockAlarm)
{
CString strError;
strError.Format("%d: Socket创建失败", WSAGetLastError());
AfxMessageBox(strError, MB_OK);
closesocket(m_sockAlarm);
return FALSE;
}
m_sockaddrinAlarm.sin_family = AF_INET;
m_sockaddrinAlarm.sin_addr.s_addr = INADDR_ANY;//inet_addr(m_strAlarmAddr);//INADDR_ANY;
m_sockaddrinAlarm.sin_port = htons(m_nAlarmPort);//htons(0);
if(SOCKET_ERROR ==(bind(m_sockAlarm, (SOCKADDR*)&m_sockaddrinAlarm, sizeof(m_sockaddrinAlarm/*SOCKADDR*/))))
{
AfxMessageBox(_T("绑定失败-报警Socket"), MB_ICONINFORMATION + MB_OK);
return FALSE;
}
m_srvaddrAlarm.sin_family = AF_INET;
m_srvaddrAlarm.sin_addr.s_addr = inet_addr(m_strAlarmAddr);
m_srvaddrAlarm.sin_port = htons(m_nAlarmPort);
//if (SOCKET_ERROR == (m_sockAlarm.Connect((LPSOCKADDR)&m_srvaddrAlarm, sizeof(m_srvaddrAlarm))))
//{
//AfxMessageBox("Windows Sockets Error", MB_OK);
//return FALSE;
//}
/*
CMainFrame* pMainFrame = new CMainFrame;
pMainFrame->LoadFrame(IDR_MENU_DISPATCH);
if (pMainFrame->m_hWnd == AfxGetMainWnd()->m_hWnd)
{
AfxMessageBox("OK");
}
*/
//WSAAsyncSelect(m_sockAlarm, this->GetSafeHwnd(), WM_ALARMSOCK, FD_READ);
//CMainFrame* pMainFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd;
//WSAAsyncSelect(m_sockAlarm, pMainFrame->m_hWnd, WM_ALARMSOCK, FD_READ);
WSAAsyncSelect(m_sockAlarm, this->m_hWnd, WM_ALARMSOCK, FD_READ);
m_srvaddrAlarm.sin_family = AF_INET;
m_srvaddrAlarm.sin_addr.s_addr = inet_addr(m_strAlarmAddr);
m_srvaddrAlarm.sin_port = htons(m_nAlarmPort);
return TRUE;
}
//接收处理报警
LRESULT CMainFrame::OnReceiveAlarmSock(WPARAM wParam, LPARAM lParam)
{
char Buffer[4096];
int len;
int flen = sizeof(m_srvaddrAlarm);
CString value;
CString strType="报警", strDate, strTime, strSource, strSort, strEvent, strUser="中心";
m_srvaddrAlarm.sin_port = htons(m_nAlarmPort);

CUdpDemoListView* m_pListView = (CUdpDemoListView*)m_wndSplitter.GetPane(1, 0);
CListCtrl* m_pListCtrl = (CListCtrl*)&m_pListView->GetListCtrl();
int nIndex = 0;
switch (WSAGETSELECTEVENT(lParam))
{
case FD_READ:
{
len = recvfrom(m_sockAlarm, Buffer, sizeof(Buffer), 0, (LPSOCKADDR)&m_srvaddrAlarm, &flen);
value = Buffer;
nIndex = value.Find(',', 0);//严格来说,还需处理字符特殊情况,如连着逗号,空格等:,, ,1,......
if (nIndex > 0)
{
strDate = value.Left(value.Find(' ', 0));
strTime = value.Mid(value.Find(' ', 0)+1, nIndex-1-value.Find(' ', 0));
value.Delete(0, nIndex+1);
}
nIndex = value.Find(',', 0);
if (nIndex > 0)
{
strSource = value.Left(nIndex);
value.Delete(0, nIndex+1);
}
nIndex = value.Find(',', 0);
if (nIndex > 0)
{
strSort = value.Left(nIndex);
value.Delete(0, nIndex+1);
}
nIndex = value.Find(',', 0);
if (nIndex > 0)
{
//strSource = value.Left(nIndex) + "/t" + strSource;
value.Delete(0, nIndex+1);
}
nIndex = value.GetLength();
if (nIndex > 0)
{
strEvent = value;
}

int nRow = m_pListCtrl->GetItemCount();
m_pListCtrl->InsertItem(nRow, strType, 0);
m_pListCtrl->SetItemText(nRow, 1, strDate);
m_pListCtrl->SetItemText(nRow, 2, strTime);
m_pListCtrl->SetItemText(nRow, 3, strSource);
m_pListCtrl->SetItemText(nRow, 4, strSort);
m_pListCtrl->SetItemText(nRow, 5, strEvent);
m_pListCtrl->SetItemText(nRow, 6, strUser);
m_pListCtrl->EnsureVisible(nRow, TRUE);

}
// dispose value;
break;
default:;
}

return 0L;
}
//同步报警(报警菜单ON_COMMAND命令)
void CMainFrame::OnSysAlarm()
{
m_bAlarm = !m_bAlarm;
if (m_bAlarm)
{
m_bAlarm = CreateAlarmSocket();
if (!m_bAlarm)
{
closesocket(m_sockAlarm);
}
}
else
{
closesocket(m_sockAlarm);
}
}
//报警菜单ON_UPDATE_UI命令
void CMainFrame::OnUpdateSysAlarm(CCmdUI* pCmdUI)
{
pCmdUI->SetCheck(m_bAlarm);
}