Software & Finance - Monthly Magazine Online

Volume 2 - Issue 4

April 2012




April 2012 - Technology - Sample UDP Broadcast Server in C++

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.

 

 

// 
#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(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(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  
#include  
#include  
#include  
#include  
#include  
int _tmain(int argc, TCHAR* argv[]) 
{ 
   if(argc < 3) 
   { 
      std::cout << "Error in Syntax: UDPServer.exe  "; 
      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

 

c:\> UDPServer.exe 1818 "Thanks for using softwareandfinance.com by Kathir"