Click here to Skip to main content
13,290,735 members (75,294 online)
Click here to Skip to main content
Add your own
alternative version

Stats

88.8K views
43 bookmarked
Posted 29 Nov 2006

Sending & Receiving UDP Datagrams with MFC's CAsyncSocket C++ Class

, 5 Dec 2006
Rate this:
Please Sign up or sign in to vote.
A simple example to show the use of the MFC CAsyncSocket class to send and receive UDP datagrams

Introduction

The following code is intended to provide a very simple example of how to use Microsoft MFC’s CAsyncSocket class to send and receive UDP datagrams.

I was unable to find a simple example of how to use CAsynSocket to send & receive UDP datagrams, so I created my own. I thought others might find it useful. The example shown creates two independent send sockets & a single receiver socket, that will receive data from both senders.

Using the Code

To reduce clutter, I have:

  1. included only code relevant to the UDP communications (all socket class code is included, much application code is not).
  2. created separate classes to deal with sending UDP & receiving UDP

The code snippets of my test applications main dialog, UdpTestAppDlg (.cpp & .h), show how to use the simple UdpReceiveSocket & UdpSendSocket classes that I have provided here. The example code shown creates two independent send sockets & a single receiver socket. The receive socket will receive datagrams from both senders.

The rudimentary error handling that is included is sufficient to highlight the commonest socket problems.

// Receiving Socket Class definition
#pragma once
#include <afxtempl.h>

// UdpReceiveSocket command target
class UdpReceiveSocket : public CAsyncSocket
{
      void OnReceive(int nErrorCode);
public:
      UdpReceiveSocket();
      virtual ~UdpReceiveSocket();
};
// Receiving Socket Class implementation
// UdpReceiveSocket.cpp : implementation file
//
#include "stdafx.h"
#include "UdpTestApp.h"
#include "UdpReceiveSocket.h"

// UdpReceiveSocket
UdpReceiveSocket::UdpReceiveSocket()
{
      // Just specify input PORT#, local machine is assumed
      BOOL bRet = Create(9122,SOCK_DGRAM,FD_READ);
      if (bRet != TRUE)
      {
             UINT uErr = GetLastError();
             TCHAR szError[256];
             wsprintf(szError, "Server Receive Socket Create() failed: %d", uErr);
             AfxMessageBox(szError);
      }
}

UdpReceiveSocket::~UdpReceiveSocket()
{
}

// UdpReceiveSocket member functions
void UdpReceiveSocket::OnReceive(int nErrorCode)   
{
  static int i=0;

  i++;

  TCHAR buff[4096];
  int nRead;

  CString strSendersIp;

  UINT uSendersPort;

  // Could use Receive here if you don't need the senders address & port
  nRead = ReceiveFromEx(buff, 4096, strSendersIp, uSendersPort); 

  switch (nRead)
  {
  case 0:       // Connection was closed.
     Close();      
     break;
  case SOCKET_ERROR:
     if (GetLastError() != WSAEWOULDBLOCK) 
     {
        AfxMessageBox ("Error occurred");
        Close();
     }
     break;
  default: // Normal case: Receive() returned the # of bytes received.
     buff[nRead] = 0; //terminate the string (assuming a string for this example)
     CString strReceivedData(buff);       // This is the input data    
  }
  CAsyncSocket::OnReceive(nErrorCode);
}
// Sending Socket Class definition
#pragma once
// UdpSendSocket
class UdpSendSocket : public CAsyncSocket
{
      bool m_bReadyToSend;
public:
      UdpSendSocket();
      virtual ~UdpSendSocket();
      //
      virtual bool Send(const void* lpBuf, int nBufLen ); 
      virtual void OnSend(int nErrorCode);
};
// Sending Socket Class implementation
// UdpSendSocket.cpp : implementation file
//

#include "stdafx.h"
#include "UdpTestApp.h"
#include "UdpSocket.h"

// UdpSendSocket
UdpSendSocket::UdpSendSocket():m_bReadyToSend(false)
{
      // Create a socket for sending
      // **DO NOT SPECIFY DESTINATION ADDRESS HERE**
      BOOL bRet = Create(0,SOCK_DGRAM,FD_WRITE);
      if (bRet != TRUE)
      {
             UINT uErr = GetLastError();
             TCHAR szError[256];
             wsprintf(szError, "Send Socket Create() failed: %d", uErr);
             AfxMessageBox(szError);
      }
}

UdpSendSocket::~UdpSendSocket()
{
}

// UdpSendSocket member functions
void UdpSendSocket::OnSend(int nErrorCode)
{
  m_bReadyToSend = true;    // The socket is now ready to send
  CAsyncSocket::OnSend(nErrorCode);
}

bool UdpSendSocket::Send(const void* lpBuf, int nBufLen)
{
      if ( ! m_bReadyToSend )
             return(false);
      m_bReadyToSend = false;
      int dwBytes;
      CAsyncSocket *paSocket = this;
      // Specify destination here (IP number obscured - could use computer name instead)
      if ((dwBytes = CAsyncSocket::SendToEx
	((LPCTSTR)lpBuf,nBufLen,9122,"172.XX.XX.XXX")) == SOCKET_ERROR)
      {
             UINT uErr = GetLastError();
             if (uErr != WSAEWOULDBLOCK) 
             {
                    TCHAR szError[256];
                    wsprintf(szError, "Server Socket failed to send: %d", uErr);
                    AfxMessageBox(szError);
             }
             return(false);
      }
      return(true);
// UdpTestAppDlg.cppvoid CUdpTestAppDlg::SendUdpDatagram()
{
CString strTestMessage = "Hello World";
m_ussSendSocket1.Send(strTestMessage.GetBuffer(),strTestMessage.GetLength()+1);
m_ussSendSocket2.Send(strTestMessage.GetBuffer(),strTestMessage.GetLength()+1);
}
// UdpTestAppDlg.h : header file
//

#pragma once
#include "UdpReceiveSocket.h"
#include "UdpSendSocket.h"

// CUdpTestAppDlg dialog
class CUdpTestAppDlg : public CDialog
{
…
// Implementation
protected:
      HICON m_hIcon;
      UdpReceiveSocket       m_ursReceiveSocket;       // Receive socket
      UdpSendSocket              m_ussSendSocket1;     // Just holds Ip & port # for send
      UdpSendSocket              m_ussSendSocket2;     // Just holds Ip & port # for send
      void SendUdpDatagram();
…
};//

Points of Interest

It turns out that using CAsyncSocket to send & receive UDP messages is quite straightforward, once you know how. The Microsoft documentation covers both TCP & UDP, which tends to obscure how simply this can be achieved. The other problem, lack of a simple example, has hopefully been addressed here.

The example above sends & receives strings. It is a good idea to keep UDP messages small for a number of reason, however it is a simple matter to send a buffers of bytes (e.g. based on a byte-aligned structure). ALthough non-essential in this example, it is also good practice to convert Microsoft Windows Intel alignment to network byte order before sending & to convert back when processing received data, using functions like ntohl().

License

This article, along with any associated source code and files, is licensed under A Public Domain dedication

Share

About the Author

Member 1385698
Web Developer
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Comments and Discussions

 
Questionwsastartup Pin
bkelly1320-Mar-17 8:10
memberbkelly1320-Mar-17 8:10 
AnswerRe: wsastartup Pin
Rick York20-Mar-17 9:12
memberRick York20-Mar-17 9:12 
QuestionDownload? Pin
ulatekh11-Jan-16 5:59
memberulatekh11-Jan-16 5:59 
BugUsing 'OnSend' with m_bReadyToSend is buggy Pin
CarstenBPoulsen23-Feb-14 11:08
memberCarstenBPoulsen23-Feb-14 11:08 
GeneralError Comming while creation Pin
buntyrolln5-Jun-08 20:34
memberbuntyrolln5-Jun-08 20:34 
GeneralRe: Error Comming while creation Pin
Member 138569811-Jun-08 7:07
memberMember 138569811-Jun-08 7:07 
AnswerRe: Error Comming while creation Pin
buntyrolln11-Jun-08 22:46
memberbuntyrolln11-Jun-08 22:46 
GeneralRe: Error Comming while creation Pin
shine joseph2-Sep-08 4:45
membershine joseph2-Sep-08 4:45 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.171207.1 | Last Updated 5 Dec 2006
Article Copyright 2006 by Member 1385698
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid