📄 multicastdlg.cpp
字号:
// MulticastDlg1.cpp : implementation file
//
#include "stdafx.h"
#include "Multicast.h"
#include "MulticastDlg.h"
#include "OptionDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Self-defined windows message
#define WM_NETWORKEVENT WM_USER + 0x100
/////////////////////////////////////////////////////////////////////////////
// CMulticastDlg dialog
CMulticastDlg::CMulticastDlg(CWnd* pParent /*=NULL*/)
: CDialog(CMulticastDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CMulticastDlg)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_strAddress = "224.0.0.8";
m_uPort = 2000;
m_strName = "flygone";
m_bConnect = FALSE;
m_hSocket = INVALID_SOCKET;
m_hGroupSocket = INVALID_SOCKET;
// Init winsock2.dll
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if (err != 0 )
return;
if (LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )
{
WSACleanup( );
return;
}
}
void CMulticastDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CMulticastDlg)
DDX_Control(pDX, IDC_MESSAGE_EDIT, m_ctlMessage);
DDX_Control(pDX, IDC_MESSAGE_COMBO, m_ctlWord);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CMulticastDlg, CDialog)
//{{AFX_MSG_MAP(CMulticastDlg)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_COMMAND(ID_EXIT, OnExit)
ON_COMMAND(ID_OPTIONS, OnOptions)
ON_UPDATE_COMMAND_UI(ID_OPTIONS, OnUpdateOptions)
ON_COMMAND(ID_JOIN_GROUP, OnJoinGroup)
ON_UPDATE_COMMAND_UI(ID_JOIN_GROUP, OnUpdateJoinGroup)
ON_COMMAND(IDC_SEND_BUTTON, OnSendMessage)
ON_COMMAND(ID_DISCONNECT, OnDisconnet)
ON_UPDATE_COMMAND_UI(ID_DISCONNECT, OnUpdateDisconnect)
ON_MESSAGE(WM_NETWORKEVENT, OnNetworkEvent)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//-----------------------------------------------------------------------------
// Dialog initialization
//-----------------------------------------------------------------------------
BOOL CMulticastDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
//-----------------------------------------------------------------------------
// WM_PAINT handler
//-----------------------------------------------------------------------------
void CMulticastDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
}
}
//-----------------------------------------------------------------------------
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
//-----------------------------------------------------------------------------
HCURSOR CMulticastDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
//-----------------------------------------------------------------------------
// Command handler of "Exit"
//-----------------------------------------------------------------------------
void CMulticastDlg::OnExit()
{
OnOK();
}
//-----------------------------------------------------------------------------
// Command handler of "Options"
//-----------------------------------------------------------------------------
void CMulticastDlg::OnOptions()
{
COptionDlg optionDlg;
optionDlg.m_strAddress = m_strAddress;
optionDlg.m_uPort = m_uPort;
optionDlg.m_strName = m_strName;
if (optionDlg.DoModal() == IDOK)
{
m_strAddress = optionDlg.m_strAddress;
m_uPort = optionDlg.m_uPort;
m_strName = optionDlg.m_strName;
}
}
//-----------------------------------------------------------------------------
// Command handler of "Send" button
//-----------------------------------------------------------------------------
void CMulticastDlg::OnSendMessage()
{
// Get text
CString strWord;
m_ctlWord.GetWindowText(strWord);
// Delete white space
strWord.TrimLeft();
strWord.TrimRight();
if (strWord == "\0")
return;
// Send it
BOOL bSuc = SendText(m_strName + "@" +strWord);
// Check results
if (bSuc)
{
AppendMessage("[" + m_strName + "@S] : " + strWord + "\r\n");
m_ctlWord.AddString(strWord);
m_ctlWord.SetWindowText("");
}
else
{
AfxMessageBox("Sent failed " + strWord);
}
}
//-----------------------------------------------------------------------------
// Command handler of "Join Group"
//-----------------------------------------------------------------------------
void CMulticastDlg::OnJoinGroup()
{
const CString strMsg = "Already connect to group %s at port %u!";
if (m_bConnect)
{
CString strInformation;
strInformation.Format(strMsg, m_strAddress, m_uPort);
AfxMessageBox(strMsg);
return;
}
JoinGroup();
}
//-----------------------------------------------------------------------------
// Command handler of "Send" button
//-----------------------------------------------------------------------------
void CMulticastDlg::OnDisconnet()
{
if (!m_bConnect)
return;
closesocket(m_hSocket);
m_hSocket = INVALID_SOCKET;
m_bConnect = FALSE;
const CString strInformation = m_strName + " has left the group of " + m_strAddress
+ " at port %u!\r\n";
CString strMsg;
strMsg.Format(strInformation, m_uPort);
AppendMessage(strMsg);
}
//-----------------------------------------------------------------------------
// Helper function for sending multicast string message
//-----------------------------------------------------------------------------
BOOL CMulticastDlg::SendText(CString& strMsg)
{
if (!m_bConnect || m_hSocket == INVALID_SOCKET)
{
AfxMessageBox("Please establish a communication socket!");
return FALSE;
}
WSABUF wsaBuf;
wsaBuf.len = strMsg.GetLength();
wsaBuf.buf = strMsg.GetBuffer(wsaBuf.len);
// Send word
int iRetCode = 0;
iRetCode = WSASendTo(m_hSocket, &wsaBuf, 1, (DWORD*)&wsaBuf.len, 0,
(SOCKADDR*)&m_addrRemote, sizeof(SOCKADDR), NULL, NULL);
strMsg.ReleaseBuffer();
// Return boolean flag
return (iRetCode != SOCKET_ERROR);
}
//-----------------------------------------------------------------------------
// Helper function for appending string message to edit control
//-----------------------------------------------------------------------------
void CMulticastDlg::AppendMessage(CString& strMsg)
{
CString strContent;
m_ctlMessage.GetWindowText(strContent);
strContent += strMsg;
m_ctlMessage.SetWindowText(strContent);
}
//-----------------------------------------------------------------------------
// Helper function for join a multicast group
//-----------------------------------------------------------------------------
void CMulticastDlg::JoinGroup()
{
int iRet = 0; // return code
// Create communication socket
m_hSocket = WSASocket(AF_INET, SOCK_DGRAM, 0, NULL, 0,
WSA_FLAG_OVERLAPPED | WSA_FLAG_MULTIPOINT_C_LEAF | WSA_FLAG_MULTIPOINT_D_LEAF);
if (m_hSocket == INVALID_SOCKET)
{
AfxMessageBox("Create communication socket fail!");
return;
}
// Set socket option to reuse the port
/*
BOOL bFlag = TRUE;
int iRet = 0;
iRet = setsockopt(m_hSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&bFlag, sizeof(bFlag));
if (iRet == SOCKET_ERROR)
{
AfxMessageBox("Set socket to reuse the port fail!");
return;
}
*/
// Bind the socket to a certain address
SOCKADDR_IN addrLocal;
addrLocal.sin_family = AF_INET;
addrLocal.sin_port = htons(m_uPort);
addrLocal.sin_addr.s_addr = INADDR_ANY;
iRet = bind(m_hSocket, (SOCKADDR*)&addrLocal, sizeof(SOCKADDR));
if (iRet == SOCKET_ERROR)
{
AfxMessageBox("Bind socket error!");
closesocket(m_hSocket);
return;
}
// Set multicasting TTL option
int TTL = 8;
iRet = setsockopt(m_hSocket, IPPROTO_IP, IP_MULTICAST_TTL,
(const char*)&TTL, sizeof(int));
if (iRet == SOCKET_ERROR)
{
AfxMessageBox("Set multicasting option error!");
closesocket(m_hSocket);
return;
}
// Join multicast group
m_addrRemote.sin_family = AF_INET;
m_addrRemote.sin_port = htons(m_uPort);
m_addrRemote.sin_addr.s_addr = inet_addr(m_strAddress);
// WSABUF wsaCalleeData;
m_hGroupSocket = WSAJoinLeaf(m_hSocket, (SOCKADDR*)&m_addrRemote, sizeof(m_addrRemote),
NULL, NULL, NULL, NULL, JL_BOTH);
if (m_hGroupSocket == INVALID_SOCKET)
{
AfxMessageBox("Join multicast leaf error!");
closesocket(m_hSocket);
return;
}
// Set callback routine
iRet = WSAAsyncSelect(m_hGroupSocket, m_hWnd, WM_NETWORKEVENT, FD_WRITE | FD_READ);
if (iRet == SOCKET_ERROR)
{
AfxMessageBox("Select error!");
closesocket(m_hSocket);
return;
}
m_bConnect = TRUE;
const CString strInformation = m_strName + " has joined the group of "
+ m_strAddress + " at port %u!\r\n";
CString strMsg;
strMsg.Format(strInformation, m_uPort);
AppendMessage(strMsg);
}
//-----------------------------------------------------------------------------
// Helper function for handling network event
//-----------------------------------------------------------------------------
LONG CMulticastDlg::OnNetworkEvent(WPARAM wParam, LPARAM lParam)
{
if (WSAGETSELECTERROR(lParam) != 0)
{
AfxMessageBox("Network event error!");
return 1L;
}
switch (WSAGETSELECTEVENT(lParam))
{
// We take no care about writing event
case FD_WRITE:
break;
case FD_READ:
ReceiveText();
break;
default:
break;
}
return 0L;
}
//-----------------------------------------------------------------------------
// Helper function for receiving message
//-----------------------------------------------------------------------------
void CMulticastDlg::ReceiveText()
{
char buffer[0x1000];
ZeroMemory(buffer, 0x1000);
int iRet = 0;
unsigned long ret = 0;
int iLen = sizeof(m_addrRemote);
int iFlag = 0;
WSABUF wsaRecvBuf;
wsaRecvBuf.len = 0x1000;
wsaRecvBuf.buf = buffer;
iRet = WSARecvFrom(m_hGroupSocket, &wsaRecvBuf, 1, &ret,
(unsigned long*)&iFlag, (SOCKADDR*)&m_addrRemote, &iLen, NULL, NULL);
if (iRet == SOCKET_ERROR)
{
AfxMessageBox("Error while receiving multicast message!");
return;
}
// Format the message
char* pDelimiter = strchr(buffer, '@');
*pDelimiter = '\0';
CString strName, strMsg;
strName = buffer;
strMsg = pDelimiter + 1;
AppendMessage("[" + strName + "@R] : " + strMsg + "\r\n");
}
//-----------------------------------------------------------------------------
// IDOK
//-----------------------------------------------------------------------------
void CMulticastDlg::OnOK()
{
if (m_bConnect)
closesocket(m_hSocket);
WSACleanup();
CDialog::OnOK();
}
//-----------------------------------------------------------------------------
// Update UI of "Options" command
//-----------------------------------------------------------------------------
void CMulticastDlg::OnUpdateOptions(CCmdUI* pUI)
{
pUI->Enable(!m_bConnect);
}
//-----------------------------------------------------------------------------
// Update UI of "Join Group" command
//-----------------------------------------------------------------------------
void CMulticastDlg::OnUpdateJoinGroup(CCmdUI* pUI)
{
pUI->Enable(!m_bConnect);
}
//-----------------------------------------------------------------------------
// Update UI of "Disconnect" command
//-----------------------------------------------------------------------------
void CMulticastDlg::OnUpdateDisconnect(CCmdUI* pUI)
{
pUI->Enable(m_bConnect);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -