2 Implementation of network chat procedures 2.1. Implementation method: (1) Programming with Winsock: Socket is originally a program interface in UNIX's Berkeley Software Distributiion version. He is similar to the function library of C. Simply put, Winsock is the standard interface defined between the window application and the network. Program designers find that when developing Windows network applications, just support the standard specifications of the Winsock interface, no longer need to worry about the network card hardware part used, because Winsock provides the dynamic connection library (WS2_32.dll) to complete the network. The work of the underlying communication. Furthermore, the program is designed to design more features or more friendly network software. (2) Programming with MFC Socket: Using Winsock programming, use Windows Socket API function programming has practical and flexible features, but it may be troublesome for beginners lack basic network knowledge. In view of this, Microsoft specially prepared The CasyncSocket and CSocket classes are connected to the basic Socket class. At the same time, in order to build and send data parts, the CSoKetetFile class is provided in the MFC Central (and a CSocketWnd class). 2.2. Implementation Algorithm: Now the most common and popular network programming mode is C / S mode, the server is a program or process that can provide some or some functions; the client uses some or some of the functions of the server process using each other. Procedures or processes. In the C / S mode, the server process should be started first, and then the client accesses the server resources over the network to complete the corresponding operation. There are two ways to communicate with usual network communications, which is mainly for transport layers, namely: facing connection, such as use TCP protocol; no connection, such as UDP protocols. However, sometimes for programming, use the UDP protocol is a connection-oriented process. Alternatively, how to deal with network requesting network programs can be divided into interactive and synchronous type. The interactive features are simple programming, not easy to make mistakes, but the implementation efficiency is not high; concurrently, it is relatively complex, not easy to control, but the execution efficiency is high. There are many ways to concurrent achievements, with the two main two: 1. Creating a thread is a client service. 2. Use the event driver. In one thread, it can be manipulated by asynchronous I / O operations. When there is an event, the corresponding process is triggered. (1) Use Winsock programming algorithm: 1. Connect the connection mode (TCP protocol) server side: <1> First use the WSAStartup function to initialize the network environment. <2> Call the Socket (AF_INET, SOCK_STREAM, 0) function to create a socket. <3> Call the BIND function Associate the local address with the original socket. <4> Call the Listen function to listen to the connection request to the socket. <5> The client's connection request is placed in the connection request queue, the server calls the Accept function to remove the first request from the connection request queue, create a new socket for service, the socket processing all with the customer Interactive information. The listening socket of the server process continues to process connection requests from other customers until the arrival of new connection requests is waiting for the queue.
<6> Call CloseSocket () Close the listening sleeve, release the socket resource. <7> Call the WSacleanup function to release the corresponding resources. Client: <1> First use the WSAStartup function to initialize the network environment. <2> Call the Socket (AF_INET, SOCK_STREAM, 0) function to create a socket. <3> Call the Connect function to connect the remote server to request a service. <4> After the server is connected to the request, the client process starts with the interaction of the server until the request is completed. <5> Call CloseSocket () Close the listening sleeve, release the socket resource. <6> Call the wsacleanup function to release the corresponding resources. 2. No connection (UDP protocol)
Yes
Undistent server structure (2) with MFC Socket programming algorithm:
1. CasynvSocket class This class encapsulates the Windows Socket API function. The CasynvSocket is facing programmers who are familiar with the underlying network, allowing them to get the flexibility to use the Windows Socket API function, but also get the convenience of the network event trigger the callback function. The CasynvSocket class converts Windows messages related to socket to the callback function. Server: <1> First create an object using the CasynvSocket class, you can use the stack mode (directly declare a class object instance), or you can use the stack mode (using new, explicitly delete the object after using DELETE). <2> Call the CasynvSocket class CREATE method to create a socket, the CREATE method supports the default parameter. <3> Call the Listen method of the CasynvSocket class to listen to the connection request from the client. <4> Once the client's connection comes in, the Accept method of the CasynvSocket class is called. Before calling, you should construct a CSocket class object. <5> Communication is performed using the CasynvSocket packaged API function for just generated sockets.
<6> Once the communication is complete, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. <7> When the server is listened to the socket, press 6. Client: <1> Create an object using the CasynvSocket class, you can use the stack mode (directly declare a class object instance), or you can use a heap mode (using new, using DELETE to delete the object). <2> Call the CasynvSocket class CREATE method to create a socket, the CREATE method supports the default parameter. <3> Call the CASYNVSocket class Connect method to connect to the server. <4> Once the connection is complete, call the CasynvSocket packaged API function to communicate. <5> Once the communication is completed, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. Server program pattern: Yes
Client program pattern structure:
Void CServerdoc :: CloseSocket (CSERVICESOCKET * PSOCKET) {psocket-> close ();
POSITION pos, temp; for (pos = m_connectionList.GetHeadPosition (); pos = NULL;!) {Temp = pos; CServiceSocket * pSock = (CServiceSocket *) m_connectionList.GetNext (pos); if (pSock == pSocket) {m_connectionList .Removeat (temp); Break;}}
Delete psocket; psocket = null;} 2.csocket class CSocket class is derived from the CasynvSocket class, inherits the standard Windows Socket API function of the CasynvSocket package, while the CSocket class is Windows Socket API function compared to the CasynvSocket class. Deeply abstract abstraction. The CSocket class typically processes sends and receives data with the CSocketFile class and the CARCHIVE class. The CSocket object also provides blocking operation functions, which is a necessary condition for the Cachive synchronization operation. Block operation functions such as: Receive, Send, RecieveFrom, Sendto, and Accept, do not return to WSAEWOULDBLOCK errors in CSocket, in contrast, these functions have been completed until the operation is completed. Server: <1> First use the CSocket class to create an object, you can use the stack mode (directly declare a class object instance), or you can use a heap mode (using new, using DELETE to delete the object). <2> Call the CSocket class CREATE method to create a socket, the CREATE method supports the default parameter. <3> Call the Listen method of the CSocket class to listen to the connection request from the client. <4> Once the client's connection comes in, call the CSocket class ACCEPT method. Before calling, you should construct a CSocket class object. <5> Create a CSocketFile object and associate it with the CSocket object requested by the handled customer request. <6> Creating a CARCHIVE object is used to receive and send data for the socket object and associate him with the CSocketFile object. Note that a CARCHIVE object should be created for sending and receiving data parts, while CARCHIVE cannot process data of SOCK_DGRAM types. <7> Use the CARCHIVE object to send data and receive data. <8> Once the communication is completed, you should clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. <9> When the server monitors the socket is closed, press 6. Client: <1> Create an object using the CSocket class, you can use the stack mode (directly declare a class object instance), or you can use a heap mode (using new, using DELETE to delete the object). <2> Call the CSocket class CREATE method to create a socket, the CREATE method supports the default parameter. <3> Call the CSocket class Connect method to connect the server. <4> Create a CSocketFile object and associate it with the CSocket object requested by the handled customer request. <5> Creating a CARCHIVE object is used to receive and send data for the socket object and associate him with the CSocketFile object. <6> Use the CARCHIVE object to send data and receive data.
<7> Once the communication is complete, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. 2.3 Server four design 1. Connected concurrent server: This server uses a connection protocol and handles multiple user requests. This is generally used in the number of customer visits, and the response time requested by the customer is high, and stable and reliable service is required. 2. Connected interactive server: This server uses a connection protocol; to provide a stable, reliable service to the customer, while the server is a client request that is processed one by one. This approach applies to the amount of customer visits, the response time requirements for the customer request is not high, but at the same time, the stability and reliability of the data are high. 3. Connected parallel server: This server uses no connection protocol; you can serve multiple customers. This approach is suitable for frequent communication frequent communication, reliability, and stability requirements. 4. Connected interactive server: This server uses a connectionless protocol; the server handles the customer's communication request. This program applies to applications that require high reliability and stability, and communications are not frequent. 2.4 Practice Procedure 2.4.1 Message Structure from: Messages to: Message Receiver Type: Message Type ShortMessage: Message 2.4.2 Message Type Value User Login 1 User Exit 2 Normal Communication 3 Send to All 4 Users Requesting the reproduction person list 5 requests to specify the user IP address 6 Server shutdown 9 2.4.3 Implementation process server-side code: <1> First use the CasynvSocket class to create an object, you can use the stack mode (directly declare a class object instance), or use Pile mode (using new, delete the object after using DELETE). <2> Call the CasynvSocket class CREATE method to create a socket, the CREATE method supports the default parameter. M_psocket-> crete (m_nport) // creation
<3> Call the Listen method of the CasynvSocket class to listen to the connection request from the client. M_psocket-> listen () // listening
<4> Once the client's connection comes in, the Accept method of the CasynvSocket class is called. Before calling, you should construct a CSocket class object. Void CServerdoc :: process acquiscept ()
IF (m_psocket-> accept (* psocket)) {cMSG = new cMsg; PMSG-> shortmessage = "come in"; pmsg-> to = "; pmsg-> from ="; PMSG -> TYPE = 1; Position Posname;
For (POSNAME = m_connectionList.getHeadPosition (); PosName;) {psock = (cServicesocket *) m_connectionList.getnext (PSNAME); if (psock-> name! = pmsg-> from) {sendmsg (psock, pmsg);} Else delete psocket;
} <5> Communication for the API function encapsulated by the CasynvSocket package for just generated sockets. void CServerDoc :: SendMsg (CServiceSocket * pSocket, CMessage * pMessage) {pSocket-> SendMsg (pMessage);} CMessage * CServerDoc :: ReadMsg (CServiceSocket * pSocket) {pSocket-> ReceiveMsg (m_pShortMessage);
Return M_PshortMessage;
} Void CServicesocket :: ReceiveMsg (CMSSAGE * PMSG) {PMSG-> Serialize (* m_pachivein);
<6> Once the communication is complete, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. Void CServerdoc :: CloseSocket (CSERVICESOCKET * PSOCKET) {psocket-> close ();
POSITION pos, temp; for (pos = m_connectionList.GetHeadPosition (); pos = NULL;!) {Temp = pos; CServiceSocket * pSock = (CServiceSocket *) m_connectionList.GetNext (pos); if (pSock == pSocket) {m_connectionList .Removeat (temp); Break;}}
DELETE PSOCKET; PSOCKET = NULL;} Void CSerVerdoc :: DeleteContents () {delete m_psocket; m_psocket = null;
CString temp; temp = "Server has been shutdown!"; CMessage * pMsg = new CMessage; while {CServiceSocket * pSocket = (CServiceSocket) m_connectionList.RemoveHead () (m_connectionList.IsEmpty ()!); If (pSocket == NULL) Continue; if (pmsg == null) Continue; PMSG-> from = psocket-> name; pmsg-> shortmessage = _text ("Server Has Been Shutdown!"); PMSG-> To = _text ("all"); PMSG -> Type = 9; Sendmsg (PSocket, PMSG); if (! Psocket-> isaborted ()) {psocket-> shutdown (); byte buffer [50]; while (psocket-> receive (buffer, 50)> 0 ); Delete psocket;}} delete pmsg; cdocument :: deleteContents ();
<7> When the server monitors the socket is closed, the 5 method is processed. 2.4.4 Imported classes defined in the system (1) CMessage class: Define four variables: cstring shortmessage; cstring from; cstring to; ing type; declared CMessage () function in the CMessage class, the added value of the variable at CMessage The class declared the serialize () function, the reset () function void reset (); // changed the four variables to the initial value. Void Serialize (CARCHIVE & A); Judging Ar.isstoring () in its function, true Ar <
<
<
<
Otherwise, Ar >> Type; Ar >> ShortMessage; Ar >> from; AR >> TO;
(2) CaccPTSocket class:
This type of event listening is similar to receiving the user's connection request and creates a socket class serving the user request.
CaccPTSocket * m_pdoc;
Create a receive button onaccept
CSocket: onaccept (nerrorcode);
m_pdoc-> process ();
Overload = caccptsocket & operator = (const capcptsocket ssrc); / / for private variables
(3) CSERVICESOCKET class:
This class is created by listening sockets to implement classes that communicate with the client.
Define three member variables:
CSocketFile * m_pfile; / / CSocketfile class associated with this socket
CARCHIVE * m_PARCHIVEIN; / / The variable of the received data document associated with the CSocketFile class
CARCHIVE * m_PARCHIVEOT; / / The variable of the sending data document associated with the CSocketFile class (4) CSERVERDOC class:
This class is responsible for processing data, and the socket class is responsible for processing transmitting and receiving data, and the document class is responsible for processing data, listed in the following data transceiver and display related functions.
m_nport = 6666; // Communication port set to 6666
IF (m_psocket! = null) // If m_psocket, m_pshortmessage is not empty
Delete m_psocket; // delete
M_PSocket = NULL;
IF (M_PshortMessage! = NULL)
Delete M_PshortMessage;
M_PSocket = New Cacceptsocket (this);
IF (M_PSocket-> Create (m_nport)) // creation
IF (m_psocket-> listen ()) // listens
Return True; // Returns true;
Client code:
The client app is named Client, which is a dialog program.
Client:
<1> First use the CasynvSocket class to create an object, you can use the stack mode (directly declare a class object instance), or you can use a heap mode (using New, explicitly delete the object after using DELETE).
<2> Call the CasynvSocket class CREATE method to create a socket, the CREATE method supports the default parameter.
INT CUSERDLG :: OnCreate (lpcreatestruct lpcreatestruct)
{
m_bonline = false;
m_pmsg = new cMessage ();
CRect rect; GetClientRect (& rect); m_ListCtrl = new CUserList (); (! M_ListCtrl-> Create (WS_CHILD | WS_VISIBLE | LVS_REPORT, rect, this, IDC_LISTBOX)) if {TRACE0 ( "Failed to create view for CMyBarLeft / n") Return -1;}
M_ListCtrl-> ModifyStyleex (0, WS_EX_CLIENTEDGE); addExStyle (LVS_EX_FULLROWSELECT | LVS_OWNERDRAWFIXED); INT I; LV_COLUMN LVC;
Lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; Strtemp [2] = {"Name", "IP Address" = {"," "}; int size [2] = {140 , 40}; for (i = 0; i <2; i ) {lvc.isubitem = i; lvc.psztext = (char *) (lpctstr) strTemp [i]; lvc.cx = size [i]; lvc. FMT = LVCFMT_LEFT; M_ListCtrl-> INSERTCOLUMN (I, & LVC);
Pnid.cbsize = sizeof (notifyicondata); pnid.hicon = loading (AFXGetApp () -> m_hinstance, makeintresource (idR_mainframe)); pnid.hwnd = this-> m_hwnd; sprintf (pnid.sztip, "chat program / n")) ; pnid.uCallbackMessage = WM_SYSTRAY; pnid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; pnid.uID = ID_SYSTRAY; Shell_NotifyIcon (NIM_ADD, & pnid); if (ConnectToServer ()) {m_bOnline = TRUE; m_pMsg-> From = Name; m_pMsg- > To = "all"; m_pmsg-> type = 5; m_pmsg-> shortmessage = "hello"; m_psocket-> sendmsg (m_pmsg);} else m_bonline = false;
CString M_STRTEMP; this-> getWindowText (m_strtemp); m_strtemp = "-"; m_strtemp = name; this-> setWindowText (m_strtemp); return 0;}
<3> Call the CASYNVSocket class Connect method to connect to the server. Bool Cuserdlg :: ConnectTOSERVER () {if (m_bonline) Return True;
M_PSocket = New CserveSocket (this)
IF (m_psocket == null) {AFXMessageBox ("COULDN '' Allocate Memory for Service Socket!"); Return False;}
if {delete m_pSocket; m_pSocket = NULL; AfxMessageBox ( "Create Socket Error!"); return FALSE;} (m_pSocket-> Create ()!) m_pSocket-> Name = Name;! while (m_pSocket-> Connect (m_strAddress, m_nPort )) {IF ("RETRY AGAIN?", MB_YESNO == IDNO) {delete m_psocket; m_psocket = null; returnaf false;}}
m_psocket-> init ();
m_pmsg-> from = Name; m_pmsg-> to = "all"; m_pmsg-> type = 1; m_pmsg-> shrMsSage = "come in ...."; m_psocket-> sendmsg (m_pmsg);
m_bonline = true;
Return True;
}
<4> Once the connection is complete, call the CasynvSocket packaged API function to communicate. void CUserDlg :: SendMsg () {CMsgDlg m_dlgMsg; m_dlgMsg.m_bSend = TRUE; m_dlgMsg.m_strFrom = Name; m_dlgMsg.m_strTo = m_pMsg-> To; if (m_dlgMsg.DoModal () == IDOK) {m_pMsg-> ShortMessage = m_dlgMsg .m_strMsg; m_pMsg-> Type = 3; m_pSocket-> SendMsg (m_pMsg);}} void CUserDlg :: ReceiveMsg () {CString m_strTemp; int m_nPosition; int m_nPrePos; m_pMsg-> Serialize (* m_pSocket-> m_pArchiveIn); switch (m_pmsg-> type) {casse 1: m_listctrl-> additem (1, m_pmsg-> from.getBuffer (0), "" ", Break; Case 2: M_ListCtrl-> Remove (m_pmsg-> from.getBuffer (0) Break; Case 3: Displaymsg (); Break; Case 4: DisplayMSG (); Break; Case 5: M_ListCtrl-> deleteallItems (); m_nposition = -1; m_nprepos = 0; m_nposition = m_pmsg-> shortmessage.find "##", 0); while (m_nposition! = -1) {m_strtemp = m_pmsg-> shortmessage.mid (m_nprepos, m_nposition - m_nprepos); if (m_strtemp.compare (name)) {m_listctrl-> additem (1, m_strtemp.getBuffer (0), "");} m_nprepos = m_nposition 2; m_nposition = m_pmsg-> shortm Essage.find ("##", m_nprepos;
<5> Once the communication is completed, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. Void Cuserdlg :: OnClose () {if (! M_psocket) {delete m_psocket; m_psocket = null;} IF (m_pmsg! = Null) delete m_pmsg; cdialog :: onClose ();}
<7> Use the CARCHIVE object to send data and receive data. Void Cuserdlg :: DisplayMSG () {cmsgdlg m_dlgmsg; cstring m_strtemp;
IF (m_pmsg-> from == ") RETURN; if (m_pmsg-> from == Name) return; m_strtemp = m_pmsg-> from; m_dlgmsg.m_bsend = false; if (m_pmsg-> to ==" ") m_dlgmsg .m_strTo = Name; else if (m_pMsg-> To == "All") m_dlgMsg.m_strTo = Name; else m_dlgMsg.m_strTo = m_pMsg-> To; m_dlgMsg.m_strMsg = m_pMsg-> ShortMessage; m_dlgMsg.m_strFrom = m_pMsg-> FROM;
if (m_dlgMsg.DoModal () == IDOK) {m_pMsg-> From = Name; // m_pMsg-> To = m_dlgMsg.m_strTo; m_pMsg-> To = m_strTemp; m_pMsg-> ShortMessage = m_dlgMsg.m_strMsg; m_pMsg-> Type = 3; m_psocket-> sendmsg (m_pmsg);
} <8> Once the communication is completed, you will clear the object. For objects on the stack, the object is automatically released when the function returns, and the object generated using the New operator is released using the delete operator. Non-explicit calling close methods because the constructor of this class automatically calls the Close method. <9> When the server monitors the socket is closed, press 6. The class defined in the system; CMessage class: Delicate from the COBJECT class, the purpose is to use the serialization function of the COBJECT class to send the data from the document associated with the service socket. CACCEPT class: is a listener socket class for listening to the user's connection request. Once there is a user connection request, this calls its member function to create a service socket class (3) CSERVICESOCKET class: is a socket class that serves user requests that the socket class handles all sent and received data, in Class define three member variables csocketfile * m_pfilecarchive * m_parchIveincarchive * m_parchiveout The first variable is associated with the socket class, the second variable is the received data document associated with CSocketFile, the third variable is Sending a data documentation associated with CSocketFile. This socket object is implemented with the above-mentioned portfolio to transmit and receive data functions.