Click here to Skip to main content
Click here to Skip to main content

Socket Programming with MFC (Part 1)

By , 9 Nov 2005
 
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

About the Author

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

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
Hint: For improved responsiveness ensure Javascript is enabled and choose 'Normal' from the Layout dropdown and hit 'Update'.
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 4memberiampradeepsharma26 Feb '13 - 19:22 
GeneralMy vote of 2memberMember 92600623 Jan '13 - 21:41 
GeneralMy vote of 5membernethajiprasath26 Jun '12 - 0:56 
QuestionClient?memberL12345M629 Mar '11 - 5:49 
Questiontelnet send: only 64 characters at one time?memberL12345M69 Mar '11 - 4:14 
QuestionHow to add a timeout?memberL12345M68 Mar '11 - 3:24 
AnswerRe: How to add a timeout?memberL12345M614 Mar '11 - 4:53 
GeneralMFC project optionsmemberbkelly1319 Nov '10 - 16:43 
QuestionHow to communicate between TCP Client and UDP Server.memberksrithesh18 Feb '10 - 20:25 
General[Message Deleted]memberit.ragester2 Apr '09 - 21:56 
Questionhow to create multi client communicationmemberN.Ravi Raj1 Dec '08 - 18:05 
Hai! This article is super and using this i am able to commuincate a server and a client.But i am not able to commuincate with multi client. Server is able to send messages to recently connected client.But server not able to receive messages from it. How to make the multi client communication.Pre thanks to your valuable suggestions.
GeneralConnecting multiple clients to one port.memberTpasta2 Jul '08 - 5:14 
GeneralRe: Connecting multiple clients to one port.memberL12345M620 Mar '11 - 23:50 
GeneralRe: Connecting multiple clients to one port.memberL12345M621 Mar '11 - 3:41 
QuestionHow can i do UDP socket programmingmemberbuntyrolln5 Jun '08 - 19:30 
Generalgood sourcememberAhn Jung Woo13 Sep '07 - 17:39 
GeneralSocket multi-languagememberproITer4 Sep '07 - 18:34 
Questionproblem with connecting to a server.membernishchal_devnur25 Jun '07 - 0:30 
QuestionUsing CAsyncSocket in a Console Application ???memberlutzTobias19 Apr '07 - 2:30 
QuestionPlease explain the objective of this project...membershampyshanky24 Mar '07 - 23:22 
AnswerRe: Please explain the objective of this project...memberthenotwist28 Jul '07 - 14:12 
Generalproblem in transfeering contextsmemberVishwas Bharadwaj7 Feb '07 - 8:15 
QuestionHow to test this application?memberMikeRT23 Nov '06 - 19:28 
AnswerRe: How to test this application?memberJobin Wilson29 Nov '06 - 19:30 
GeneralRe: How to test this application?memberbertszoghy30 Jan '07 - 13:01 

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

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