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

📄 multicastdlg.cpp

📁 面向软件工程的Visual C++网络程序开发
💻 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 + -