MFC NETWORK COMMUNICATION + WEB BROWSING
NETWORK COMMUNICATION BETWEEN COMPUTERS WITH TCP/IP
Apps running on different computers can communicate with each other
Server App: Waits for other apps on other computers to open a communication connection
Client App: Attempts to open a connection
When connection is established, data can be exchanged
Either can close the communication
Connections:
Two programs running on different computers form a connection
Data is sent and received along the connection
Sockets:
Basic object used to perform network communication
Used to read/write messages travelling between applications
(Like a file pointer in file I/O)
A communication "endpoint"
There's a socket at each end of the connection
Windows support for sockets: in the Winsock API
MFC encapsulates this in the CAsyncSocket base class
Provides complete, event-driven socket communications
Lowest level support
Higher level support from derived classes like CSocket
Making a socket connection to another app:
Specify IP address of computer the other app is running on
Identifies a machine
Also specify the port the app listening on
Identifies the program that should handle the communication
E.g. port 80 for web document transfers
Like telephone communication: (Dial number and extension)
CAsyncSocket class support:
Provides for complete event-driven network communication
Facilitates creation of sockets & establishing/closing connections
Manages data transfer
We can define our own m_sock class derived from CAsyncSocket
Objects constructed from this class will have socket functionality
Use 2 AsyncSocket objects: m_L (listening socket) & m_C (communication data socket)
Creating a Socket:
Server: m_L.Create(listen port #); // A Listening socket
Client: m_C.Create(); // Client Connection socket for Data
Server: m_C // Server Connecton socket for Data
Making a Connection:
Server: m_L.Listen();
Client: m_C.Connect("IPnameOrAddress", port #);
Server: m_L.Accept(m_C); // Creates the server side m_C Connection socket for Data
Server is listening
Connection attempt--> "request connection messsage" event sent to server
Event triggers call to Server's overridable m_L.OnAccept()
==> It should call its Accept(m_C) method
==> m_C Data socket is created automatically & connected to client
Result: "connection accepted message" event to client (he can now send)
Event triggers call to Client's overridable m_C.OnConnect()
Sending/receiving text data:
Sender invokes m_C.Send(lpszDataSring,length)
When data is received, receiver gets "data received message" event
Event triggers call to receiver's overridable m_C.OnReceive()
==> Receiver should invoke m_C.Receive(lpszBuf,length)
Should fill the buffer with the received data
Closing a connection:
Either party can invoke m_C.Close()
==>other party gets "close connection message" event
Event triggers call to overridable to m_C.OnClose()
==>Should call m_C.Close()
Sends a "close connection message" event to other party...
who should do the same thing
<Show Powerpoint here>
Socket “Msg Handler” Virtual Functions: Socket “Action” Functions:
Override-- Call at correct times--
Connection accepted --> OnConnect() Create()
Request connection --> OnAccept() Listen() -- server
Data received --> OnReceive() Connect() -- client
Close connections --> OnClose() Accept() -- server
Send()
Receive()
Close()
ClientSock and ServeSock Applications <Show programs in action>
MFC AppWizard Dialog-based applications
After network connection is made, either can send or receive strings
Need to define CMySock class derived from CAsyncSocket
m_sock object from this class will be receiving messages over the network
In response it must call functions defined in its parent dialog box class
So need member variable that points to the parent window:
CDialog m_pWnd
Need member function that will provide the parent window pointer:
void CMySock::SetParent(CDialog *pWnd)
{
m_pWnd = pWnd;
}
Must override the following base class virtual member functions:
(Want corresponding functions to be called in parent dialog box)
OnConnect() <Client only>
OnAccept() <Server only>
OnReceive()
OnClose()
Preparing the ServeSock Server App (details)
MFC AppWizard Dialog-based application
Under "Advanced Features" check "Windows Sockets"
Controls:
Static Control: "ListenPort"
Single-line Edit box: IDC_ESERVPORT
Button: "Connect", IDC_BCONNECT
Button: "Send", IDC_BSEND
Button: "Close", IDC_BCLOSE
Static Control: "Message:"
Single-line Edit box: IDC_EMSG
Static Control: "Sent:"
List box: IDC_LSENT
Static Control: "Received:"
List box: IDC_LRECVD
Attach variables to the controls:
IDC_EMSG: m_sMsg, Value, CString
IDC_ESERVPORT: m_iPort, Value, int
IDC_LRECVD: m_cRecvd, Control, CListBox
IDC_LSENT: m_cSent, Control, CListBox
Add Message Map handler functions for BN_CLICK messages for each new button:
IDC_BCONNECT --> OnBconnect()
IDC_BSEND --> OnBsend()
IDC_BCLOSE --> OnBclose()
Create the Socket Class: CMySock
In Classview, right click on top node (ServeSock Classes)
Select: Add, Add Class; Select MFC, MFC Class
Name: CMySock, Base Class: CAsyncSocket
Add private member variable to CMySock:
name: m_pWnd
type: CDialog*
Add public member function to CMySock:
void SetParent(CDialog* pWnd)
Edit SetParent() by adding the line:
m_pWnd = pWnd;
In properties window of CMySock add event override functions:
OnAccept(int nErrorCode)
OnReceive(int nErrorCode)
OnClose(int nErrorCode)
For each, parameter in declaration should be: int nErrorCode
Edit each of these new functions following pattern of OnAccept() given here:
void CMySock::OnAccept(int nErrorCode)
{
if(nErrorCode==0)
//Call parent dialog's OnAccept() function
((CServeSockDlg*)m_pWnd)->OnAccept();
}
Include the header file for the dialog box in new CMySock class:
#include "ServeSockDlg.h" in MySock.cpp
Add two private CMySock variables to CServeSockDlg class:
m_listensock
m_datasock
Add the following public void member functions to CServeSockDlg class:
OnAccept()
OnReceive()
OnClose()
Add initialization code to CServeSockDlg::OnInitDialog() function:
// TODO: Add extra initialization here
m_iPort=4000; //unused port number
UpdateData(FALSE); //send data to controls
m_datasock.SetParent(this); //the 2 MySocket objects
m_listensock.SetParent(this);
Edit CServeSockDlg::OnBConnect() handler function:
// TODO: Add your control notification handler code here
UpdateData(TRUE); //get string from control
m_listensock.Create(m_iPort); //create socket
m_listensock.Listen(); //listen on socket
Edit CServeSockDlg::OnAccept():
m_listensock.Accept(m_datasock); //accept connection, create data socket
Edit CServeSockDlg::OnBSend():
// TODO: Add your control notification handler code here
int iLen;
int iSent;
UpdateData(TRUE); //get string from control
if (m_sMsg!="")
{ //send it out the socket
iLen=m_sMsg.GetLength();
iSent=m_datasock.Send(LPCTSTR(m_sMsg),iLen);
if (iSent==SOCKET_ERROR)
{MessageBox("Server send error");
}
else
{ //add string to Sent box
m_cSent.AddString(m_sMsg);
UpdateData(FALSE); //send data to control
}
Edit CServeSockDlg::OnReceive():
char *pBuf = new char[1025];
int iBufSize=1024;
int iRecvd;
CString sRecvd;
iRecvd=m_datasock.Receive(pBuf,iBufSize); //get strng from socket
if(iRecvd==SOCKET_ERROR)
{}
else
{ //add string to Received box
pBuf[iRecvd]=0; //terminating NULL
sRecvd=pBuf;
m_cRecvd.AddString(sRecvd);
UpdateData(FALSE); //send data to control
}
Edit CServeSockDlg::OnClose():
m_datasock.Close(); //close the data socket
Edit CServeSockDlg::OnBclose():
OnClose(); //call above function that closes the data socket
Enhancing the ServeSock App--
Disable and disable the "Connect", "Send", & "Close" buttons...
and the "Message" and "Listen Port" Edit controls...
at the appropriate times--
Add Control variables:
m_cConnect to IDC_BCONNECT button
m_cSend to IDC_BSEND button
m_cClose to IDC_BCLOSE button
m_cMsg to IDC_EMSG edit control
m_cPort to IDC_ESERVPORT edit control
and invoke their EnableWindow() function at correct times.
Preparing the ClientSock Client Application
Most of project same as ServerSock
Some Differences:
Dialog box needs "Server Name" Edit Control:
(So user can specify DNS name or IP address & enable/disable it)
Only need one CMySock object: m_datasock
OnInitDialog() should be changed--extra initialization
Need an OnConnect() function instead of OnAccept()
OnBConnect() will be changed
OnClose() will be changed
Running the ServeSock and ClientSock:
Applications will only work if computer(s) have TCP/IP installed and configured correctly
Be sure the Server connects before a client tries to connect
Test first with both applications on the same machine
Servername = "loopback" (default as programmed)
Then try with server on one machine and client on another
Client must enter:
correct "name" or "IP address" of computer server is running on
Port number Server is listening on
One problem: The server application can handle only one connection at time.
A second application trying to connect to connected server will cause server to crash.
One soution: A third socket object could be used to send a rejection message to other
clients attempting to connect if another client is still connected.
WINDOWS WEB BROWSING & HYPERTEXT MARKUP LANGUAGE (HTML)
MFC Support for Web Browsing
New in VC++ 6
HTML--
Scripting Language to create Web Pages
VC++ Support for HTML--
WebBrowser Control
ActiveX component provides access to Inernet Explorer browsing components
MFC CHtmlView class
Wraps WebBrowser control into package that fits into Doc/View arch.
Provides easy access to Internet Explorers functions
Views derived from CHtmlView are basic Web browser windows
Requires Microsoft Internet Explorer 4.0 (or later) installed
Some CHtmlView member functions:
Navigate ("URL")
GoBack()
GoForward()
GoHome()
GoSearch()
Stop()
Refresh()
LoadFromResource()
CString GetLocationURL()
BOOL GetBusy()
Adding DHTML Documents to Windows Programs:
1. As a resource:
Project / Add Resource / HTML / New /
Then right click to get to "View HTML Source"
Then enter html script
Finally in code, Load HTML resource using LoadFromResource()
2. Or Load from a file:
Navigate("file_name")
3. Or Download from a remote site
Navigate("URL")
HtmlSample Application <Show program in action>
Allows user to browse the web:
Go to home page
Navigate to a URL entered in a dialog box
Load a web page from a file using the common file dialog box
Load a web page whose html is defined in the program's resources
MFC AppWizard, SDI Application
In "User Features" select "Standard Docking" and "Browser Style" under Toolbars
In "Generated Classes" select CHtmlView as the base class for CHtmlSampleView
Add Pop-up Menu Item "Browse" with items:
"URL": ID_BROWSE_URL (-->Dialog box w/ edit control to enter URL)
"File": ID_BROWSE_FILE (--> Common file dialog box to get file name)
"Home": ID_BROWSE_HOME (--> Go to browser's home page)
"Resource": ID_BROWSE_RESOURCE (--> Load html page from pgm's resources)
Insert Simple HTML page resource:
Project / Add / Resource / HTML / New
Right click and select "View HTML Source"
Enter something like the following text in the editor window:
<html>
<body>
<h3> This page was stored as a resource for this program</h3>
<h2> My favorite Web page is:</h2>
<A HREF="http://www.binghamton.edu">
Binghamton University Home Page</>
</body>
</html>
This will generate resource IDR_HTML1 in a file called html1.htm
Insert a "URL" Dialog Box Resource:
Static Control: "Enter URL"
Edit Box: "IDC_EURL
Add a new Dialog box class:
CUrlDlg based on CDialog
Add a CString member variable to CUrlDlg:
IDC_EURL: variable name = m_EURL
Use ClassWizard to add menu command message map handler functions in CHtmlSampleView:
ID_BROWSE_URL: OnBrowseUrl()
ID_BROWSE_FILE: OnBowseFile()
ID_BROWSE_HOME: OnBrowseHome()
ID_BROWSE_RESOURCE: OnBrowseResource()
Edit each of the handler functions:
OnBrowseUrl():
// TODO: Add your command handler code here
CUrlDlg dlg;
if (dlg.DoModal()==IDOK) //Invoke URL dialog box
Navigate(dlg.m_eURL);
OnBowseFile():
// TODO: Add your command handler code here
CFileDialog fdlg(TRUE);
CString sFileName;
if (fdlg.DoModal()==IDOK) //Invoke common file dlg box
{
sFileName=fdlg.GetPathName(); //Get file name
Navigate(sFileName);
}
OnBrowseHome():
// TODO: Add your command handler code here
GoHome();
OnBrowseResource():
// TODO: Add your command handler code here
LoadFromResource(IDR_HTML1);
Edit the code in OnInitialUpdate()
Change the line:
Navigate2(_T("http://www.microsoft.com/visualc/"),NULL,NULL);
to:
Navigate("http://www.SomeValidURL");
Here SomeValidURL would be some web address you know is OK, perhaps your home page
Add #include "UrlDlg.h" near top of htmlSampleView.cpp
Build and run the application--
Make sure you're connected to the Internet
Computer must have Microsoft Internet Explorer installed