Quickly implement network programming using MFC
Fuzhou University Wang Jun
---- With the in-depth of computer network, computer network programming has become increasingly important in programming. Due to the superiority of the C language on the underlying operation, many articles have been introduced to use VC for Socket programming methods. However, since it is directly using dynamic connection wsock32.dll, it is more cumbersome. In fact, the VC MFC class library provides a socket class such as CasyncSocket, which is very convenient to implement Socket programming.
---- This article will use an ECHO routine to introduce the usage of the CasyncSocket class.
---- One. Client
---- 1. Create a Dialog Based project: CSockClient.
---- 2. Design dialog
---- Remove the OK and CANCLE two buttons, add ID_connect (connection), ID_send button, add the ListBox control IDC_LISTMSG and Edit control idc_editmsg, and press the table to add variables for CCSockClientDlg class in ClassWizard .
Control ID Type MEMBER
IDC_EDITMSG CEDIT M_MSG
IDC_LISTMSG CLISTBOX M_MSGS
---- 3. The CasyncSocket class processes the MFC message with the Docallback function. When a network event occurs, the DOCALLBACK function is called on Network Event Type: fd_read, fd_write, fd_accept, fd_connect, respectively calls OnReceive, OnSend, OnAccept, ONCONNECT functions. Since the MFC defines these event handlers as a virtual function, you have to generate a new C class to overrunate these functions, the practice is as follows:
---- Inheriting the CasyncSocket class in a public manner, generating new class mysock;
---- Add virtual functions for MySOCK classes onreceive, onConnect, Onsend
---- 4. Add the following code in MySock.ccp
#include "csockclient.h"
#include "csockclientdlg.h"
---- 5. Add the following code to mysock.h
PUBLIC:
BOOL M_BCONNECTED; / / Whether
UINT M_NLENGTH; // Message Length
Char m_szbuffer [4096]; // message buffer
---- 6. Heavy load function in mysock.ccp
Mysock :: mysock ()
{
m_nlength = 0;
Memset (m_szbuffer, 0, sizeof (m_szbuffer);
m_bconnected = false;
}
Mysock :: ~ mysock ()
{
// Close the socket
IF (m_hsocket! = invalid_socket)
CLOSE ();
}
Void mysock :: OnRecEive (int NerrorCode)
{
m_nlength = Receive (m_szbuffer, sizeof (m_szbuffer), 0);
// The following two lines of code are used to obtain the dialog pointer
CCSockClientApp * PAPP = (ccsockclientapp *) AFXGetApp ();
CcSockClientdlg * PDLG = (ccsockclientdlg *) PAPP-> m_pmainwnd; pdlg-> m_msgs.insertstring (0, m_szbuffer);
Memset (m_szbuffer, 0, sizeof (m_szbuffer);
CasyncSocket :: OnRecEive (NerrorCode);
}
Void mysock :: Onsend (int NerrorCode)
{
Send (m_szbuffer, m_nlength, 0);
m_nlength = 0;
Memset (m_szbuffer, 0, sizeof (m_szbuffer);
/ / Continue to draw a "read" network event to receive the Server message
Asyncselect (fd_read);
CasyncSocket :: Onsend (NerrorCode);
}
Void mysock :: OnConnect (int NerrorCode)
{
IF (NerrorCode == 0)
{
m_bconnected = true;
CCSockClientApp * PAPP = (ccsockclientapp *) AFXGetApp ();
CcSockClientdlg * PDLG = (ccsockclientdlg *) PAPP-> m_pmainwnd;
Memcpy (M_SZBuffer, "Connected to", 13);
Strncat (m_szbuffer, pdlg-> m_szserveradr,
SizeOf (PDLG-> M_SZSERVERVERADR);
PDLG-> m_msgs.insertstring (0, m_szbuffer);
Asyncselect (fd_read); Select a "read" network event, ready to receive
}
CasyncSocket :: onConnect (NERRORCODE);
}
---- 7. New dialog IDD_ADDR, used to enter IP addresses and port; generate new class Caddrdlg. Add two edit controls: IDC_ADDR, IDC_Port Press the table to add variables for the Caddrdlg class in ClassWizard.
Control ID Type MEMBER
IDC_ADDR CSTRING M_ADDR
IDC_PORT INT M_PORT
---- 8. Add code in csockclientdlg.ccp
#include "addrdlg.h"
protected:
INT TRYCOUNT;
Mysock m_clientsocket;
Uint m_szport;
PUBLIC:
Char m_szserveradr [256];
---- 9. Double-click the "Connection" button in the IDD_CSockClient_Dialog dialog box, add the following code
Void ccsockclientdlg :: onConnect ()
{
m_clientsocket.shutdown (2);
m_clientsocket.m_hsocket = invalid_socket;
m_clientsocket.m_bconnected = false;
Caddrdlg m_dlg;
// Default port 1088
m_dlg.m_port = 1088;
IF (m_dlg.domodal () == iDok &&! m_dlg.m_addr.isempty ())
{
Memcpy (m_szserveradr, m_dlg.m_addr, sizeof (m_szserveradr));
m_szport = m_dlg.m_port;
/ / Establish a timer, try to connect once every 1 second until it is connected or trycount> 10Settimer (1, 1000, null);
Trycount = 0;
}
}
---- 10. Add Windows Message WM_TIMER Response Function Ontimer
Void ccsockclientdlg :: Ontimer (uint nidevent)
{
IF (m_clientsocket.m_hsocket == invalid_socket)
{
Bool bflag = m_clientsocket.create (0, SOCK_STREAM, FD_CONNECT);
IF (! bflag)
{
AFXMessageBox ("Socket Error!");
m_clientsocket.close ();
PostquitMessage (0);
Return;
}
}
m_clientsocket.connect (m_szserveradr, m_szport);
Trycount ;
IF (trycount> = 10 || m_clientsocket.m_bconnected)
{
Killtimer (1);
IF (Trycount> = 10)
AfxMessageBox ("Connect Failed!");
Return;
}
CDIALOG :: ONTIMER (Nidevent);
}
---- 11. Double-click the "Send" button in the IDD_CSockClient_Dialog dialog box, add the following code
Void ccsockclientdlg :: Onsend ()
{
IF (m_clientsocket.m_bconnected)
{
m_clientsocket.m_nlength = m_msg.getWindowText
(m_clientsocket.m_szbuffer, sizeof (m_clientsocket.m_szbuffer);
m_clientsocket.asyncselect (fd_write);
m_msg.setwindowText ("");
}
}
---- 12. Double-click the "Close" button in the IDD_CSockClient_Dialog dialog box, add the following code
Void ccsockclientdlg :: Onexit ()
{
// Close Socket
m_clientsocket.shutdown (2);
// Close dialog
Enddialog (0);
}
----
12. Run this project, enter the host name or IP when the connection is connected, and the CasyncSocket class will automatically process.
----
two. Server
----
Server end programming is similar to the Client side, which mainly introduces his Listen and Accept functions.
----
1. Create a CNEWSocket class, overreeNCSocket classes, onreceive, onsend functions, how to display and send information about information, can refer to the Client program. In this example, the method of receiving the information is not sent back to the original situation is used to implement the ECHO function, and the code is as follows.
CNewsocket :: OnReceive (int NerrorCode)
{
m_nlength = Receive (m_szbuffer, sizeof (m_szbuffer), 0);
// Direct forwarding message
Asyncselect (fd_write);
}
CNewsocket :: Onsed (int Nerror) {
Send (m_szbuffer, m_nlength, 0);
}
----
2. Create a CMYSERVERSOCKET class, the onaccept function code for the overload CasyncSocket class is as follows
----
Declaring variables in MyServersocket.h
PUBLIC ::
CNewsocket * m_psocket;
Void CMYSERVERSOCKET :: onaccept (int NerrorCode)
{
// So the connection request, call the accept function
CNewsocket * psocket = new cnewsocket ();
IF (ACCEPT (* psocket))
{
PSocket-> asyncselect (fd_read);
m_psocket = psocket;
}
Else
DELETE PSOCKET;
}
----
3. Add a "listening" button to the dialog, add the following code
----
Declaring variables in csockserverdlg.ccp
PUBLIC:
CMYSERVERSOCKET M_SRVRSOCKET;
Void ccsockServerdlg :: online ()
{
IF (m_srvrsocket.m_hsocket == invalid_socket)
{
Bool bflag = m_srvrsocket.create
(Userport, Sock_Stream, FD_ACCEPT);
IF (! bflag)
{
AFXMessageBox ("Socket Error!");
M_srvrsocket.close ();
PostquitMessage (0);
Return;
}
}
// "Listening" success, waiting for the connection request
IF (! m_srvrsocket.listen (1))
{
INT NERRORCODE = m_srvrsocket.getlasterror ();
IF (NERROR! = WSAEWOULDBLOCK)
{
AFXMessageBox ("Socket Error!");
M_srvrsocket.close ();
PostquitMessage (0);
Return;
}
}
}
----
4. The current program can only implement the ECHO function, forward the information, if you can't move, if you can use the CNEWSocket * psocket = new cnewsocket (); get the Socket pointer to a CLIST or an array, like the Client side, Read and write all connections. ----
three. to sum up
----
The CasyncSocket class provides us with Socket to provide great convenience. Establishing a Socket's WSAStartup process and Bind procedures are simplified to become create processes, IP address type conversions, host names, and IP address translations. Many complex variable types are simplified into strings and integers, especially asynchronous features of CasyncSocket classes. Can fully replace the cumbersome thread operation. The MFC provides a large number of libraries, and if we can use them flexibly, we will greatly improve the efficiency of programming.