Visual C++ Socket Programming - UDP Broadcast Server Application and Client Application
I have come up with a UDP Broadcast Server Application that sends a data packet to all machines connected in the local network on a particular port. The server application is a Win32 Console Application and Client application is MFC Dialog based application.
You can run the client application in any numbers of machines connected in the local network. Once you execute a message from UDP broadcast server application, all clients will get in one shot.
The complete source code and executable links are given at the bottom of this page.
Source Code
// UDPClientDlg.h : header file
//
#pragma once
#include "afxwin.h"
// CUDPClientDlg dialog
class CUDPClientDlg : public CDialog
{
// Construction
public:
CUDPClientDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
enum { IDD = IDD_UDPCLIENT_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
void StartListening();
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnTimer(UINT_PTR nIDEvent);
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
SOCKET m_clientsocket;
CString m_recvData;
CEdit m_editCtrl;
afx_msg void OnBnClickedOk();
int m_portno;
afx_msg void OnBnClickedCancel();
};
#include "stdafx.h"
#include "UDPClient.h"
#include "UDPClientDlg.h"
// CUDPClientDlg dialog
CUDPClientDlg::CUDPClientDlg(CWnd* pParent /*=NULL*/)
: CDialog(CUDPClientDlg::IDD, pParent)
, m_recvData(_T(""))
, m_portno(1818)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CUDPClientDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_EDIT1, m_recvData);
DDX_Control(pDX, IDC_EDIT1, m_editCtrl);
DDX_Text(pDX, IDC_EDIT3, m_portno);
}
BEGIN_MESSAGE_MAP(CUDPClientDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_WM_TIMER()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDOK, &CUDPClientDlg::OnBnClickedOk)
ON_BN_CLICKED(IDCANCEL, &CUDPClientDlg::OnBnClickedCancel)
END_MESSAGE_MAP()
// CUDPClientDlg message handlers
BOOL CUDPClientDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 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
return TRUE; // return TRUE unless you set the focus to a control
}
void CUDPClientDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CUDPClientDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<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 function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CUDPClientDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CUDPClientDlg::OnBnClickedOk()
{
StartListening();
SetTimer(0x1, 100, NULL);
GetDlgItem(IDOK)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT3)->EnableWindow(FALSE);
//OnOK();
}
void CUDPClientDlg::StartListening()
{
UpdateData(TRUE);
m_clientsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(m_clientsocket == -1)
{
MessageBox("Error in creating socket");
return;
}
//struct hostent *hostentry = gethostbyname(m_serveraddr);
//char *pipaddr = inet_ntoa (*(struct in_addr *)*hostentry->h_addr_list);
//UDPserveraddr.sin_addr.s_addr = inet_addr(pipaddr);
SOCKADDR_IN UDPserveraddr;
memset(&UDPserveraddr,0, sizeof(UDPserveraddr));
UDPserveraddr.sin_family = AF_INET;
UDPserveraddr.sin_port = htons(m_portno);
UDPserveraddr.sin_addr.s_addr = INADDR_ANY;
int len = sizeof(UDPserveraddr);
if(bind(m_clientsocket, (SOCKADDR*)&UDPserveraddr,sizeof(SOCKADDR_IN)) < 0)
{
MessageBox("ERROR binding in the server socket");
return;
}
}
void CUDPClientDlg::OnTimer(UINT_PTR nIDEvent)
{
fd_set fds;
struct timeval timeout;
timeout.tv_sec = 0;
timeout.tv_usec = 100;
FD_ZERO(&fds);
FD_SET(m_clientsocket, &fds);
int rc = select(sizeof(fds)*8, &fds, NULL, NULL, &timeout);
if(rc > 0)
{
char rbuf[1024];
SOCKADDR_IN clientaddr;
int len = sizeof(clientaddr);
if(recvfrom(m_clientsocket,rbuf, 1024, 0, (sockaddr*)&clientaddr, &len) > 0)
{
for(int i = 1024; i >= 1; i--)
{
if(rbuf[i] == '\n' && rbuf[i - 1] == '\r')
{
rbuf[i-1] = '\0';
break;
}
}
char *p = inet_ntoa(clientaddr.sin_addr);
int serverportno = ntohs(clientaddr.sin_port);
CString rData;
rData.Format("%s\r\nBroadcast Server: %s \r\n%s\r\n\r\n", (const char*)CTime::GetCurrentTime().Format("%B %d, %Y %H:%M:%S"), p, rbuf);
m_recvData = rData + m_recvData;
UpdateData(FALSE);
}
}
CDialog::OnTimer(nIDEvent);
}
void CUDPClientDlg::OnBnClickedCancel()
{
ShellExecute(NULL, _T("open"), _T("http://www.softwareandfinance.com"), NULL, NULL, SW_SHOWNORMAL);
OnCancel();
}
// UDPServer.cpp : Defines the entry point for the console application.
//
#include <stdio.h>
#include <tchar.h>
#include <winsock2.h>
#include <string>
#include <iostream>
#include <atlbase.h>
int _tmain(int argc, TCHAR* argv[])
{
if(argc < 3)
{
std::cout << "Error in Syntax: UDPServer.exe <port no> <msg>";
return 0;
}
int portno = ::_wtoi(argv[1]);
USES_CONVERSION;
char *p = W2A(argv[2]);
WORD w = MAKEWORD(1,1);
WSADATA wsadata;
::WSAStartup(w, &wsadata);
SOCKET s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if(s == -1)
{
std::cout << "Error in creating socket";
return 0;
}
char opt = 1;
setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&opt, sizeof(char));
SOCKADDR_IN brdcastaddr;
memset(&brdcastaddr,0, sizeof(brdcastaddr));
brdcastaddr.sin_family = AF_INET;
brdcastaddr.sin_port = htons(portno);
brdcastaddr.sin_addr.s_addr = INADDR_BROADCAST;
int len = sizeof(brdcastaddr);
char sbuf[1024];
sprintf(sbuf, "%s\r\n", p);
int ret = sendto(s, sbuf, strlen(sbuf), 0, (sockaddr*)&brdcastaddr, len);
if(ret < 0)
{
std::cout << "Error broadcasting to the clients";
}
else if(ret < strlen(sbuf))
{
std::cout << "Not all data broadcasted to the clients";
}
else
{
std::cout << "Broadcasting is done";
}
::closesocket(s);
return 0;
}
Click here to download the Visual C++ source code and executable file
Output
c:\> UDPServer.exe 1818 "Thanks for using softwareandfinance.com by Kathir"
|