Click here to Skip to main content
Click here to Skip to main content
Go to top

Socket Programming with MFC (Part 1)

, 9 Nov 2005
Rate this:
Please Sign up or sign in to vote.
An article on Socket Programming with MFC
Sample Image - MFCSockets.jpg

Introduction

Socket Programming is a very interesting activity in most of the programming languages. It's a nice activity to write Servers and Clients that communicate over a network. In Windows Platform, socket communications are based on Microsoft Winsock architecture. Windows supports both stream based (TCP) and Datagram based (UDP) socket communication. Windows APIs are available for socket programming, but many find it difficult to work with them.

So here I am going to explain the easiest way to do socket programming using MFC socket classes. This will not only make your job easy, but will also reduce the development time for your network applications. You can develop a custom made socket class that you can reuse in all the network based applications that you write. I will explain these concepts by developing an Echo Server application.

The MFC Socket Classes

For Socket programming, MFC provides two built in classes named CAsyncSocket and CSocket. CSocket is inheriting its functionality from CAsyncSocket. CAsyncSocket class provides several notification functions ,that will be called automatically upon occurrence of the socket events. Moreover, it acts as the base class for the complete event driven socket communication.

We can create our own customised socket classes by inheriting from CAsyncSocket class, which will serve our application specific needs. At first socket environment needs to be initialized by calling the AfxSocketInit() function.

Initializing Sockets

To initialize sockets, we need to call the function AfxSocketInit(). It is usually called from the InitInstance() function of the MFC application. If we are using a wizard to generate the application, checking the option "use Windows Sockets" will automatically do this job for us. It returns a value to indicate success or failure of the call.

BOOL CEchoServerApp::InitInstance()
{....
if( AfxSocketInit() == FALSE)
  { 
  AfxMessageBox("Sockets Could Not Be Initialized"); 
  return FALSE; 
  }
  ...
}

Creating Server Sockets

To create a Server socket, we need to declare a variable of type CAsyncSocket or our own class derived from CAsyncSocket or CSocket. Then we must call the create() function with the port to be listened as argument. It returns a value to indicate success or failure of the call:

UpdateData(TRUE);
m_sListener.Create(m_port);
if(m_sListener.Listen()==FALSE) 
{ 
AfxMessageBox("Unable to Listen on that port, please try another port"); 
m_sListener.Close(); 
return; 
}

Creating Client Sockets

To create a Client socket, first we need to declare a variable of type CAsyncSocket or our own class derived from CAsyncSocket or CSocket. Then we must call the create() function without any arguments. It returns a value to indicate success or failure of the call:

m_sConnected.Create();
m_sConnected.Connect("server ip",port);

Listening for Incoming Connections

For making the server socket listen to the Specific port, we must call the function Listen(). It returns a value to indicate success or failure of the call:

if( m_sListener.Listen()== FALSE) 
{ 
AfxMessageBox("Unable to Listen on that port, please try another port"); 
m_sListener.Close(); 
return;
}

Accepting Connections

The incoming connection must be accepted to another socket (not the listening socket). It is done by calling the Accept function with the second socket as argument.

void CEchoServerDlg::OnAccept()
{
 CString strIP; 
 UINT port; 
 if(m_sListener.Accept(m_sConnected)) 
 {
  m_sConnected.GetSockName(strIP,port); 
  m_status="Client Connected,IP :"+ strIP; 
  m_sConnected.Send("Connected To Server",strlen("Connected To  Server"));      
UpdateData(FALSE); 
 }
 else 
 { 
 AfxMessageBox("Cannot Accept Connection"); 
 } 
}

Sending Data

The data to be sent is kept in a buffer and a pointer to it and its length is passed to the send function:

m_sConnected.Send(pBuf,iLen);

Receiving Data

Data is received by calling the function receive(buffer,maxlength):

void CEchoServerDlg::OnReceive() 
{ 
char *pBuf =new char [1025]; 
CString strData; 
int iLen;
iLen=m_sConnected.Receive(pBuf,1024);    
if(iLen == SOCKET_ERROR)      
  {
  AfxMessageBox("Could not Receive");      
  }      
else     
  { 
  pBuf[iLen]=NULL;
  strData=pBuf;
  m_recieveddata.Insert(m_recieveddata.GetLength(),strData); 
 //display in server              
 UpdateData(FALSE); 
 m_sConnected.Send(pBuf,iLen);  //send the data back to the Client   
 delete pBuf;          
  } 
}

Shutting Down Connection

m_sConnected.ShutDown(0);    Stops  Sending Of Data 
m_sConnected.ShutDown(1);    Stops Receiving of data
m_sConnected.ShutDown(2);    Stops Both Sending and Receiving of Data

Closing Connection

m_sConnected.Close();

Socket Events

Several functions are used for notification of events. They are to be overridden by descendant classes, in the form of protected member functions.

  1. OnAccept() indicates that a connection is pending to be accepted
  2. OnClose() indicates that application at the other end has closed the socket
  3. OnConnect() indicates that Connection establishment is complete
  4. OnSend() indicates that Data is being sent
  5. OnReceive() indicates that Data is being received
  6. OnOutofBandData() indicates that out of band data (urgent message) has arrived

Deriving Our Own Socket Class from CAsyncSocket

For deriving our own socket class, go to class view and add a new class and set its base class as CAsyncSocket. With the help of classwizard, add notification functions as shown below:

class MyEchoSocket : public CAsyncSocket
{ // Attributes 
public: 
 // Operations
public: 
MyEchoSocket(); 
virtual ~MyEchoSocket(); 
// Overrides 
public: 
void SetParentDlg(CDialog *pDlg);// ClassWizard generated virtual function overrides 
//{{AFX_VIRTUAL(MyEchoSocket) 
public: 
virtual void OnAccept(int nErrorCode);
virtual void OnClose(int nErrorCode);
virtual void OnConnect(int nErrorCode);
virtual void OnOutOfBandData(int nErrorCode);
virtual void OnReceive(int nErrorCode); 
virtual void OnSend(int nErrorCode); 
//}}AFX_VIRTUAL // Generated message map functions 
//{{AFX_MSG(MyEchoSocket) 
// NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG 
protected: 
private:
CDialog * m_pDlg; 
};

Setting The "Parent Dialog"

The socket class's SetParentDlg function is called to ensure that notifications are received to the dialog class when socket events occur:

m_sListener.SetParentDlg(this); 
m_sConnected.SetParentDlg(this);

Linking Socket Events With Dialog Class Member Functions

In the dialog class, add the appropriate functions like:

void OnReceive(); 
void OnClose(); 
void OnAccept(); 
void OnConnect();

These functions are called from the socket class as shown below:

void MyEchoSocket::OnAccept(int nErrorCode) 
{ 
// TODO: Add your specialized code here and/or call the base class 
if(nErrorCode==0) 
{ 
((CEchoServerDlg*)m_pDlg)->OnAccept(); 
}
CAsyncSocket::OnAccept(nErrorCode); 
} 

Using the Code

The attached project is ready to be compiled and executed. Just open with Visual C++ 6.0 and compile. It is an EchoServer that echoes back whatever data is sent to it. You can use a telnet client to connect to it. The sending and receiving functionality can be tested easily from telnet console.

History

  • Version 1.0, Part 1 of MFC Socket Programming [ 10/11/2005 ]

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Jobin Wilson
Web Developer
United States United States
http://jobinwilson.blogspot.com/

Comments and Discussions

 
QuestionError C3861: 'AfxSocketInit': identifier not found Pinmemberindra30405-Nov-13 19:50 
GeneralMy vote of 5 PinmemberJasMineLeaf17-Oct-13 21:23 
QuestionSetParentdlg Pinmemberyossisw25-Aug-13 23:38 
GeneralMy vote of 5 PinmemberMember 1012532125-Jun-13 4:55 
Questionthankssssss PinmemberMember 999976523-May-13 8:02 
GeneralMy vote of 4 Pinmemberiampradeepsharma26-Feb-13 19:22 
GeneralMy vote of 2 PinmemberMember 92600623-Jan-13 21:41 
GeneralMy vote of 5 Pinmembernethajiprasath26-Jun-12 0:56 
QuestionClient? PinmemberL12345M629-Mar-11 5:49 
Questiontelnet send: only 64 characters at one time? PinmemberL12345M69-Mar-11 4:14 
QuestionHow to add a timeout? PinmemberL12345M68-Mar-11 3:24 
AnswerRe: How to add a timeout? PinmemberL12345M614-Mar-11 4:53 
GeneralMFC project options Pinmemberbkelly1319-Nov-10 16:43 
QuestionHow to communicate between TCP Client and UDP Server. Pinmemberksrithesh18-Feb-10 20:25 
Please give me an example for TCP Client communicates with a UDP Server.
I am new to socket programming.
I have to develop an application which is TCP Socket, it should interact with UDP based Hardware.
Please give me some Idea and Example.
 
Advance thanks for the Reply.
 
Srithesh.
General[Message Deleted] Pinmemberit.ragester2-Apr-09 21:56 
Questionhow to create multi client communication PinmemberN.Ravi Raj1-Dec-08 18:05 
GeneralConnecting multiple clients to one port. PinmemberTpasta2-Jul-08 5:14 
GeneralRe: Connecting multiple clients to one port. PinmemberL12345M620-Mar-11 23:50 
GeneralRe: Connecting multiple clients to one port. PinmemberL12345M621-Mar-11 3:41 
QuestionHow can i do UDP socket programming Pinmemberbuntyrolln5-Jun-08 19:30 
Generalgood source PinmemberAhn Jung Woo13-Sep-07 17:39 
GeneralSocket multi-language PinmemberproITer4-Sep-07 18:34 
Questionproblem with connecting to a server. Pinmembernishchal_devnur25-Jun-07 0:30 
QuestionUsing CAsyncSocket in a Console Application ??? PinmemberlutzTobias19-Apr-07 2:30 
QuestionPlease explain the objective of this project... Pinmembershampyshanky24-Mar-07 23:22 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140916.1 | Last Updated 10 Nov 2005
Article Copyright 2005 by Jobin Wilson
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid